多线程面试_12

CAS(Compare and Swap)

Java 平台中的锁包括内部锁(排它锁)( Intrinsic Lock )和显式锁 ( Explicit Lock )。内部锁是通过synchronized关键字实现的;显式锁是通过java.concurrent.locks.Lock接口的实现类(如 java.concurrent.locks.ReentrantLock 类 ) 实现的。

synchronized(ReentrantLock)这种锁属于悲观锁,即它始终都觉得会发生并发冲突,所以会屏蔽一切可能打破数据完整性的操作.
同时,还有一种锁叫乐观锁,即它觉得不会发生并发冲突,因此只在提交操作时检查是否违反数据完整性这些规则. 如果提交失败,它就会进行重试,乐观锁最常见的就是这里要说的CAS了.

CAS是一种高效实现线程安全性的方法
CAS机制主要是发生于Java中原子操作类(JUC)的底层实现中,它就是一种底层的实现思想,我们不会去直接使用它,我们使用的都是它包装好的类.

  • 支持原子更新操作,适用于计数器,序列发生器(即给变量自增的工具)等场景.
  • 属于乐观锁,号称lock-free
  • CAS操作失败时由开发者决定是否尝试,还是执行别的操作,由此执行失败的线程不会被阻塞挂起,只会告知你失败了.
  • CAS一定要与volatile变量配合使用,这样才能保证线程每次拿到的变量都是主内存中最新的那个值
  • atomic包下的原子类就是使用的CAS机制

CAS思想

  • CAS的操作包含三个操作数: 内存位置(C),预期原值(A)新值(B).
  • 执行CAS操作的时候,将内存位置的值(即主内存的值)与预期原值进行比较,如果相匹配,那么处理器就会将该内存位置的值更新为新值,否则处理器不做任何操作.
  • 例如:当一个线程想要修改共享变量的值,那么它首先在主内存中取出该值的副本或引用赋值给A,然后用A去参加运算,得到新值B,执行完毕需要更新共享变量的值的时候,就调用CAS方法区更新变量的值.

CAS多数情况下对开发者是透明的

  • J.U.C的atomic包提供了常见的原子性数据类型以及引用,数组等相关原子类型的更新操作工具,是很多线程安全程序的首选.
  • Unsafe类虽然提供了CAS服务,但因能操纵任意内存地址读写而由隐患.
  • java9以后,可以使用Variable Handle API来替代Unsafe.

CAS缺点

  1. 若循环时间长,开销会很大.
  2. 只能保证一个共享变量的原子操作.
  3. ABA问题

如果内存地址C初次读取的值为A,并且在准备赋值的比较的时候,它的值仍然为A,此时我们就可以说它的值没有被其他线程改变过了吗?
他有可能被改变成了B然后又改变回了A. 但是CAS却会认为他没有被改变过.

解决方法: 它提供了一个带有标记的原子引用类AtomicStampedReference,它可以通过控制变量值的版本来保证CAS的正确性.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值