zoukankan      html  css  js  c++  java
  • atomic原子类的理解

    1.AtomicInteger等原子类的底层都是由Unsafe类的CAS思想和自旋锁实现。

    2.CAS思想是把自己的期望值和主存中的值进行比较,如果相同就赋值,不同就不赋值。CAS是CPU原语,是操作系统底层一系列指令实现,这些指令是连续的,所以是原子的。一般用到CAS的地方都有自旋,即先从主存中获取到值,然后执行CAS,如果主存中的值与刚获取的值相等,就赋要更新的值(下表中的update)。

    1、//这是AtomicInteger类的CAS
    public final boolean compareAndSet(int expect, int update) {//expect是期望值,用来与主存中的值进行比较,如果相同就把主存中的值改成update return unsafe.compareAndSwapInt(this, valueOffset, expect, update);//底层是调用unsafe类中的nativa方法 }
    2.//这个是AtomicInteger类中的获取并加1的方法
    public final int getAndIncrement() {
        //调用unsafe类中方法,valueOffset是这个对象在主存中的地址变量,也叫地址偏移量
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    /**
     *调用的unsafe类中源码
     *其实是先从主存中获值,然后再执行CAS,如果比较不相同,再从新获取值,执行CAS,一 
     * 直自旋
     */
    public final int getAndAddInt(Object var1, long var2, int var4) {
       int var5;
       do {//利用do-while自旋
           var5 = this.getIntVolatile(var1, var2);//从主存中获取值
       } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//执行CAS
    
       return var5;
    }
    

    3.CAS与Sychronized的比较

      Synchronized是对一个对象加锁,锁的是整个对象,数据一致性可以保证,但并发性降低;

      而CAS没有用锁,是使用自旋的方式,先从内存中取值,然后再比较赋值,并发性和数据一致性都有了保证

    4.CAS的缺点:

      ①CAS使用的是自旋,CPU消耗大

      ②CAS引来了ABA问题:即t1和t2两个线程都在执行修改主存中的值A(都现将A拷到了本线程的工作内存中),某一时刻t2线程先将A改成了B(此时主存中变成了B),然后又将B改成了A(主存中又变成了A),然后t1线程执行CAS,compareAndSwap(A,C),一比较,认为主存中的值和期望值相同,所以就将主存中的值改成了C,此时t1线程却不知主存中的值经历了A-B-A的过程。这种问题的解决办法是:使用原子包中的AtomicStampedReference时间戳(又叫版本号)原子引用可以解决,即为主存中的值设置一个版本号,每次CAS时不仅比较值,还要比较版本号,都相同再赋值

    ——每天一小步,进步一大步,坚持。。。

     

     

  • 相关阅读:
    java环境变量配置 tomcat配置
    asp.net 数据库连接 使用事务处理(一)
    css3 渐变gradient
    asp.net 数据库连接类 (一)
    某某系统HTML脚本植入测试
    BitmapFactory.Options.inSampleSize 的用法
    Comparator和Comparable在排序中的应用(转)
    学习PrintWriter类
    Android使用ListView注意事项
    Android之SurfaceView学习(转)
  • 原文地址:https://www.cnblogs.com/yayin/p/14160436.html
Copyright © 2011-2022 走看看