版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在页面明显位置给出原文链接。 https://blog.csdn.net/mengxiangqihangz/article/details/84311920
非阻塞 线性安全的类
import sun.misc.Unsafe;
import com.base.Unsafe.UnsafeUtil;
/**
* 利用cas算法 将 SafeEntity 设计成 一个 非阻塞 线性安全的类
* 并非完全的非阻塞,而是通过原子级操作,避免了加锁和释放锁。
* unsafe.compareAndSwapInt(this, nextOffset, now, after); 就是一个原子操作。一次只能一个线程通过。
* cas算法:全称 compare and set ,就是set之前先对比,是否等于预期值,等于预期值就set一个新的值,返回ture,
* 否则返回false
* compareAndSet() 中有一个递归调用,保证了每一次 改变 都能够成功。
* @author liangpro
*
*/
public class SafeEntity {
private int num;
private int sum;
public void numAddOne() throws Exception {
final Unsafe unsafe = UnsafeUtil.getUnsafeInstance();
long nextOffset = 0l;
long nextOffsetSum = 0l;
try {
nextOffset = unsafe.objectFieldOffset(SafeEntity.class.getDeclaredField("num"));//获取SafeEntity类的num属性的 内存偏移量。
nextOffsetSum = unsafe.objectFieldOffset(SafeEntity.class.getDeclaredField("sum"));
} catch (NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
compareAndSet(unsafe, nextOffset);
//doSomeThing();
compareAndSetSum(unsafe, nextOffsetSum);
}
public boolean compareAndSet(Unsafe unsafe,long nextOffset){
int now = this.num;
int after = now +1;
boolean flag = unsafe.compareAndSwapInt(this, nextOffset, now, after);//若this的内存偏移 nextOffset处的值为 now,则更新为 after
if(!flag){
compareAndSet(unsafe, nextOffset);//如果不成功,则再尝试修改一次。
}
return flag;
}
public boolean compareAndSetSum(Unsafe unsafe,long nextOffset){//可以为每一个线性不安全的操作,引入原子级修改操作。使整个类达到线程安全。
int now = this.sum;
int after = now + 2;
boolean flag = unsafe.compareAndSwapInt(this, nextOffset, now, after);
if(!flag){
compareAndSetSum(unsafe, nextOffset);
}
return flag;
}
public int getNum() {
return num;
}
public int getSum() {
return sum;
}
}
test类
import java.util.concurrent.CountDownLatch;
public class UnsafeTest {
public static int num;
public static CountDownLatch latch = new CountDownLatch(50);
public static void main(String[] args) throws InterruptedException {
SafeEntity safe = new SafeEntity();
for (int i = 0; i < 50; i++) {
new ThreadDemo(safe,latch).start();
}
latch.await();
System.out.println(safe.getNum());
System.out.println(safe.getSum());
}
static class ThreadDemo extends Thread{
SafeEntity safe;
CountDownLatch latch;
public ThreadDemo(SafeEntity safe,CountDownLatch latch){
this.safe = safe;
this.latch = latch;
}
public void run(){
for (int i = 0; i < 100000; i++) {
try {
safe.numAddOne();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
latch.countDown();
}
}
}
获得sun.misc.Unsafe实例的工具类
import java.lang.reflect.Field;
import sun.misc.Unsafe;
// 方法一:我们可以令我们的代码“受信任”。运行程序时,使用bootclasspath选项,指定系统类路径加上你使用的一个Unsafe路径
//java -Xbootclasspath:/usr/jdk1.7.0/jre/lib/rt.jar:. com.mishadoff.magic.UnsafeClient
public class UnsafeUtil {
public static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
public static Unsafe getUnsafe() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
}
}