美文网首页JUC并发相关
11. 并发终结之CAS

11. 并发终结之CAS

作者: 涣涣虚心0215 | 来源:发表于2020-09-26 06:50 被阅读0次

    我们都知道用Volatile修饰只能保证内存可见性, 并不保证原子性,JUC提供Atomic类,内部其实也是用Volatile保证内存可见性,但是用CAS(Compare-And-Swap)算法来保证数据的原子性(CAS是线程安全的)。
    CAS的典型使用模式:首先从V中读取值A,并根据A计算新值B,然后通过CAS以原子方式将V中的值由A变成B(只要在这期间没有任何线程将V的值修改成其他值)。
    CAS : 是硬件对于并发操作共享数据的支持。
    包含了三个操作数
    内存值V : 主存中要更新的变量
    预估值A :表示预期的值
    更新值B : 表示新值
    当且仅当V == A时,V = B,否则 V 不等于 A,意味着已经被其他线程更改,当前线程放弃此操作。
    在JDK里面提供了Unsafe类,封装了一些可用的CAS操作,AtomicInteger里面compareAndSet这个方法是调用unsafe.compareAndSwapInt这个方法,这个方法有四个参数,其中第一个参数为需要改变的对象,第二个为偏移量(即之前求出来的valueOffset的值),第三个参数为期待的值,第四个为更新后的值
    如果value的值(内存的value)与expect这个值相等,那么则将value修改为update这个值,并返回一个true,如果调用该方法时,value的值与expect这个值不相等,那么不做任何操作,并范围一个false。

    /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful. False return indicates that
         * the actual value was not equal to the expected value.
         */
        public final boolean compareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    

    Volatile的问题

    • ABA问题
      线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了,尽管CAS成功,但可能存在潜藏的问题
      ABA --> 解决方式,添加版本号,类似AtomicStampedReference(个数 被动过几次),AtomicMarkableReference( Boolean 有没有被动过)
    • CPU消耗
      CPU的耗费,如果CAS compareAndSetInt一直不成功,则会一直循环(自旋)。
    • 单个volatile变量
      只能保证一个共享变量的原子操作,不过可用采用AmoticReference类型解决这个问题。

    相关文章

      网友评论

        本文标题:11. 并发终结之CAS

        本文链接:https://www.haomeiwen.com/subject/unowhktx.html