• Java自定义cas操作


    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的获取

  • 相关阅读:
    Windows Phone 一步一步从入门到精通
    备忘录模式(Memento)
    开放封闭原则(OCP)
    建造者模式(Bulider)
    原型模式(Prototype)
    Windows Workflow Foundation(WF) 一步一步从入门到精通
    模板方法模式
    代理模式(Proxy)
    装饰模式(Decorator)
    迪米特法则(LoD)最少知识原则
  • 原文地址:https://www.cnblogs.com/luckygxf/p/10046275.html
Copyright © 2020-2023  润新知