java Unsafe工具类提供了一个方法
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有点就是不会有锁的开销,上下文切换。也有缺点,自旋浪费资源,不能对多个资源保证线程安全
这里需要注意两点
1. 使用反射获取Unsafe对象
2. 注意offset的获取