无锁机制CAS及其底层实现原理

目录

1. 利用锁的同步机制 

2.利用CAS原理完成对值的更新操作-非锁实现

3. CAS

4. ABA问题


1. 利用锁的同步机制 

class SafeCounter{
    private int count;
    
    //同一时间只有一个线程可以进入add方法
    public synchronized void add(){
        //复合操作
        this.count ++;
    }
}
public static void main(String[] args) {
        SafeCounter safeCounter = new SafeCounter();

        //多个线程都基于safeCounter对象来调用add方法
        //只有一个线程可以成功对safeCounter对象加锁
        safeCounter.add();

    }

以上方法每次只能一个线程进入,效率很低

2.利用CAS原理完成对值的更新操作-非锁实现

class SafeCounterCAS{
    private AtomicInteger count = new AtomicInteger();
    
    //同一个时间可以有多个线程进入add方法
    public void add(){
        //底层通过CAS实现线程安全
        count.getAndIncrement();
    }
}
  
    public static void main(String[] args) {
        SafeCounterCAS safeCounterCAS = new SafeCounterCAS();

        //多个线程都基于safeCounter对象来调用add方法
        safeCounterCAS.add();

    }   

3. CAS

CAS涉及三个操作数

  1. 需要读写的内存值V
  2. 预期值A
  3. 需要修改的最新值B

更新一个值,首先读写的内存值V,如果V=A,将V改变B;如果V!=A,操作就失败

比较成功就修改,比较不成功就是失败的;

线程1希望将0修改为1,读取到当前的值为0,比较成功,把0修改为1,线程2将之前读取到的0和现在的1进行比较,比较失败,所以不能交换。

  1. CAS操作是一种系统原语,属于操作系统硬件提供的功能,由若干条指令组成。在完成上述compare and swap功能过程中,是连续的不允许被中断(如果compare成功了,那么swap也一定会被执行,而不会说,compare成功了,但swap却失败)
  2.  CAS是一种非阻塞式的同步方式,当线程使用CAS更新失败时,并不会进入阻塞状,而是先采取自旋等待,期望再次尝试时能够成功,也就是不成功就一直循环执行直到成功
  3. 如果长时间不成功,会给CPU带来比较大的执行开销

4. ABA问题

如果一个变量V初次读取的时候是A值, 并且在准备赋值的时候检查到它仍然是A值,那我们就能说明它的值没有被其他线程修改过了吗?很明显是不能的,因为在这段时间它的值可能被改为其他值, 然后又改回A,那CAS操作就会误认为它从来没有被修改过。这个问题被称为CAS操作的"ABA"问题

如何解决ABA问题呢?

JDK 1.5以后的 AtomicStampedReference类就提供了解决ABA问题的能力,增加一个版本号维度。每次执行CAS操作,附加再更新一个版本号,并且保证版本号是递增更新的,那么即便A 变成B之后再变回A,版本号也不会变回最初的,以上也是在数据库中增加一个版本号。

总结

CAS带来了一种无锁解决线程同步,冲突问题

2.ABA问题导致了CAS方案的一定缺陷

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值