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时不仅比较值,还要比较版本号,都相同再赋值

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

     

     

  • 相关阅读:
    316 Remove Duplicate Letters 去除重复字母
    315 Count of Smaller Numbers After Self 计算右侧小于当前元素的个数
    313 Super Ugly Number 超级丑数
    312 Burst Balloons 戳气球
    309 Best Time to Buy and Sell Stock with Cooldown 买股票的最佳时间含冷冻期
    Java 类成员的初始化顺序
    JavaScript 全局
    HTML字符实体
    Java中的toString()方法
    JavaScript 弹窗
  • 原文地址:https://www.cnblogs.com/yayin/p/14160436.html
Copyright © 2011-2022 走看看