java Unsafe工具类提供了一个方法java
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
这个就是一个cas操做,原子操做。比较var1, 在var2偏移即offset位置的值是否为var4。若是是var4,更新为var5,返回true。不然,不作更新返回false安全
最近,听同事说了cas用到项目里面,感受高大上。学习了一下,包装了一个cas整型操做工具
import java.lang.reflect.Field; import sun.misc.Unsafe; /** * @Author: <guanxianseng@163.com> * @Description: * @Date: Created in : 2018/11/28 3:36 PM **/ public class GxfInteger { private sun.misc.Unsafe U; private long offset; private Integer value = 0; private static Object lock = new Object(); public GxfInteger(int value) throws Exception { this.value = value; Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); U = (Unsafe) f.get(null); offset = U.objectFieldOffset(GxfInteger.class.getDeclaredField("value")); } public void increament(){ value ++; } public void lockAdd(){ synchronized (lock){ value++; } } public void casIncreament(){ boolean update = false; do{ update = U.compareAndSwapObject(this, offset, value, value + 1); }while (!update); } public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
写了一测试类学习
public class GxfIntegerTest { public static void main(String[] args) throws InterruptedException, Exception { GxfInteger gxfInteger = new GxfInteger(0); int threadNum = 100; Runnable add = () -> { for(int i = 0; i < 10000; i++){ // gxfInteger.increament(); gxfInteger.casIncreament(); // gxfInteger.lockAdd(); } }; long start = System.currentTimeMillis(); Thread[] threads = new Thread[threadNum]; for(int i = 0; i < threads.length; i++){ threads[i] = new Thread(add); } for(int i = 0; i < threadNum; i++){ threads[i].start(); } for(int i = 0; i < threadNum; i++){ threads[i].join(); } System.out.println("time cost : " + (System.currentTimeMillis() - start)); // Thread.sleep(10000); System.out.println("result: " + gxfInteger.getValue()); } }
这里能够经过cas实现,线程安全。cas有点就是不会有锁的开销,上下文切换。也有缺点,自旋浪费资源,不能对多个资源保证线程安全测试
这里须要注意两点this
1. 使用反射获取Unsafe对象spa
2. 注意offset的获取线程