zoukankan      html  css  js  c++  java
  • 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的获取

  • 相关阅读:
    tomcat监控
    rsync排除文件同步
    [转载]centos7 快速安装 mariadb(mysql)
    linux下的头文件和库文件搜索路径 (转)
    用apt-get install一个软件的时候出现错误: 无法解析或打开软件包的列表或是状态文件
    模拟一个简单的基于tcp的远程关机程序(转)
    TCP连接的建立以及利用tcpdump分析连接建立的过程(转)
    UNIX网络编程(转载)
    开源代码网站(转)
    学了5天Arm,今天谈谈初学感受 (转)
  • 原文地址:https://www.cnblogs.com/luckygxf/p/10046275.html
Copyright © 2011-2022 走看看