java并发--CAS原理学习&乐观锁&悲观锁

在之前文章中验证了在多线程场景下,CAS可以保证共享变量的原子性。

此篇文章主要记录一下CAS原理的学习感悟。

 

在一般情况下,为保证数据安全性,我们可以采用synchronized修饰变量或者修饰方法。也就是说在同一时间只有一个线程能修改共享变量或者访问这个方法,其它线程都要等待。但是这样的话,也就相当于了单线程,失去了多线程的优势。

 

CAS的原理有些类似于悲观锁;

了解CAS之前,先了解一下悲观锁,乐观锁;

 

悲观锁&乐观锁

悲观锁:也就是往最坏的情况下考虑,假设会发送并发冲突的问题,所以当某个线程获取到共享资源时,会阻止别的线程获取共享资源。所以也可以称为  独占锁或者互斥锁。比如synchronized同步锁。

乐观锁:故名思意,假设不会发生并发冲突的情况。只有在最后更新修改共享资源时,才会去判断一下在从主存中拿到数据到修改数据这段时间内有没有别的线程修改了这个共享资源。如果发生了冲突就重试,如果没有冲突,就更新成功。CAS是乐观锁的一种实现方式。

【悲观锁会阻塞其它线程,乐观锁不会阻塞其它线程,如果发生冲突,会采用循环的方式一直重试,直至成功】

 

CAS实现原理

CAS主要通过三个值实现 

V:当前内存值

A:预期值

B:期待更新的值

举个栗子解释一下上面三个参数:

场景:现在有两个线程同时更改共享变量56【此时当前内存值(V)】,两个线程各自对共享变量进行+1的操作【期待更新的值(B)就为1】

因为线程1,线程2 同时访问同一个共享变量56,都会将主存中的值拷贝到自己的工作内存中【线程1,线程2的预期值(A)都是56】

假设线程1,线程2在线程竞争中,线程1能去先修改变量的值。线程1对变量修改后,并更新到主存中,这时候主存中数据变成了57。

对于线程2来说,此时内存值变成了57,和预期值56不一致。所以就会操作失败?操作失败怎么处理呢?重新获取内存中的最新值,这时候线程2的预期值就变成了57,和内存值相等。再进行更新操作。

此操作会采用循环的方式直至更新成功;

     public final int getAndAddInt(Object obj, long valueOffset, int var) {
        int expect;
        // 利用循环,直到更新成功才跳出循环。
        do {
            // 从内存中获取共享变量的最新值    valueOffset 指此共享变量在内存中的位置(偏移量)
            expect = this.getIntVolatile(obj, valueOffset);
            // expect + var表示需要更新的值,如果compareAndSwapInt返回false,说明value值被其他线程更改了。
            // 那么就循环重试,再次获取value最新值expect,然后再计算需要更新的值expect + var。直到更新成功
        } while(!this.compareAndSwapInt(obj, valueOffset, expect, expect + var));

        // 返回当前线程在更改value成功后的,value变量原先值。并不是更改后的值
        return expect;
    }

 

 就是指当两者进行比较时,如果相等,则证明共享数据没有被修改,替换成新值,然后继续往下运行;如果不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作。容易看出 CAS 操作是基于共享数据不会被修改的假设,采用了类似于数据库的commit-retry 的模式。当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

 

由此可见,AtomicInteger.incrementAndGet的实现用了乐观锁技术,调用了类sun.misc.Unsafe库里面的 CAS算法,用CPU指令来实现无锁自增。所以,AtomicInteger.incrementAndGet的自增比用synchronized的锁效率倍增。

 

参考:

https://blog.csdn.net/moakun/article/details/80144900

https://www.jianshu.com/p/a142350e9b7a

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值