• CAS方法的使用




    最近忙着复习,笔记倒是写了很多但没有整理出来,后期抽时间统一上传


    1. CAS

    在并发编程下能经常看到CAS,全名Compare and Swap(比较和交换)。是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-交换这个操作的原子性,主要是处理器级别提供了原子性操作。和重量级锁(Synchronized)对比,免去了线程上下文切换的开销,是个不错的轻量级锁


    实现原理:该方法有四个参数,分别是对象内存位置,对象中变量的偏移量,变量预期值,变量更新值。如果对象obj内存偏移量为offset的变量的值为expect,则使用update替换旧的值expect




    2. Unsafe

    JDK的Unsafe类提供了一系列的compareAndSwap*方法,下面列出这次用到的方法

    • long objectFieldOffet(Field file) 获取字段的偏移量
    • boolean compareAndSwaoInt(Object obj,long offset,int expect,int update) CAS方法

    因为Unsafe是个直接操作内存的不安全类,所以JDK规定只有BootStrap类加载器加载的类才能使用Unsafe类,比如rt.jar包下的类就可以。那么我们自定义的使用Application加载器加载的类怎么使用Unsafe呢?答案是:万能的反射,方法如下


    import sun.misc.Unsafe;
    import java.lang.reflect.Field;
    
    public class UnsafeUtil {
    
        public static Unsafe getInstance() throws NoSuchFieldException, IllegalAccessException {
            
            // 获取字段
            Field filed = Unsafe.class.getDeclaredField("theUnsafe");
            
            // 设置可访问
            filed.setAccessible(true);
            
            // 返回Unsafe实例
            return (Unsafe)filed.get(null);
        }
    }
    

    注意:使用IDEA方便,而eclipse不能直接导入import sun.misc.Unsafe,需要自行解决


    import sun.misc.Unsafe;
    import java.lang.reflect.Field;
    
    public class Test {
    
    	// 需要CAS修改的字段
        private int i = 0;
    
        public int getI() {
            return i;
        }
    
        public void setI(int i) {
            this.i = i;
        }
    
    
        public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    
            // 获取Unsafe实例
            Unsafe  unsafe = UnsafeUtil.getInstance();
    
            // 获取字段 i 的偏移量
            Test test = new Test();
            Field field = test.getClass().getDeclaredField("i");
            long offset = unsafe.objectFieldOffset(field);
    
            // CAS修改,返回布尔值
            boolean isSuccess = unsafe.compareAndSwapInt(test,offset,0,1);
    
            // 打印
            System.out.println(isSuccess);
            System.out.println(test.getI());
    
        }
    }
    

    打印

    true
    1
    


    《Java并发编程之美》

  • 相关阅读:
    js判断各个浏览器
    js中的全局函数
    js正则表达式大全(转)
    js url编码函数
    原生的ajax(json)
    原生js拖拽
    js浏览器兼容
    何为反向代理、正向代理
    dom元素循环绑定事件的技巧
    media 适屏
  • 原文地址:https://www.cnblogs.com/Howlet/p/12629408.html
Copyright © 2020-2023  润新知