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的獲取線程