Java多线程——JUC Atomic CAS的缺点

概述

本文不讨论Atomic原子操作的底层原理与实现,仅针对其缺点进行讨论QaQ。

缺点

Atomic原子操作类实质上是一个CAS操作的实现,Atomic类的缺点实质上是CAS的缺点:

  • 由于Atomic类CAS的实现中,存在do while的循环操作,在最恶劣的情况下,当前线程始终无法对比成功【预期值】,将会进行大量的循环,增加CPU的负荷,以getAndIncrement为例
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}
  • Atomic类只能保证一个共享变量的原子操作
    • 相对于synchronized可以对一段代码、一个方法进行加锁而言,Atomic的使用局限于某一个共享变量。
  • ABA问题
    • 当然,如果业务对中间过程不敏感,ABA问题就不会有什么影响。
package com.leolee.multithreadProgramming.juc.atomic;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @ClassName ABATest
 * @Description: TODO
 * @Author LeoLee
 * @Date 2021/3/1
 * @Version V1.0
 **/
public class ABATest {

    public static void main(String[] args) {

        AtomicReference<Integer> integerAtomicReference = new AtomicReference<>(100);

        int expect = integerAtomicReference.get();//100

        //ABA问题
        new Thread(() -> {
            integerAtomicReference.compareAndSet(expect, 101);
            integerAtomicReference.compareAndSet(integerAtomicReference.get(), 100);
        }, "t1").start();

        new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(integerAtomicReference.compareAndSet(expect, 102) + "\t" + integerAtomicReference.get());
        }, "t2").start();
    }
}

ABA问题解决

除了AtomicInteger、AtomicReference等,JUC还提供了AtomicStampedReference,带有时间戳的原子引用类,其原理类似于乐观锁的版本号控制。

package com.leolee.multithreadProgramming.juc.atomic;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @ClassName ABATest
 * @Description: TODO
 * @Author LeoLee
 * @Date 2021/3/1
 * @Version V1.0
 **/
public class ABATest {

    public static void main(String[] args) {
        //ABA问题解决
        AtomicStampedReference<Integer> integerAtomicStampedReference = new AtomicStampedReference<Integer>(100, 1);//初始值为100,版本号1
        new Thread(() -> {
            int stamp = integerAtomicStampedReference.getStamp();
            System.out.println("t3获取的初始版本号为:" + stamp);
            try {
                Thread.sleep(1000);//保证t4线程可以获取到与此时t3一样的版本号
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            integerAtomicStampedReference.compareAndSet(100, 101, integerAtomicStampedReference.getStamp(), integerAtomicStampedReference.getStamp() + 1);//版本号+1
            integerAtomicStampedReference.compareAndSet(101, 100, integerAtomicStampedReference.getStamp(), integerAtomicStampedReference.getStamp() + 1);//版本号+1
        }, "t3").start();

        new Thread(() -> {
            int stamp = integerAtomicStampedReference.getStamp();
            System.out.println("t4获取的初始版本号为:" + stamp);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(integerAtomicStampedReference.compareAndSet(100, 102, stamp, stamp + 1) + "\t" + integerAtomicStampedReference.getReference());
        }, "t4").start();
    }
}

//测试结果:
t3获取的初始版本号为:1
t4获取的初始版本号为:1
false	100

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值