多线程并发-CAS操作
作者:互联网
CAS操作
Compare And Swap先比较,再交换
CAS中有三个值:内存中的旧值V,期望的值A,最终的值B,一个CAS操作会先比较内存中的旧值和期望值是否相等,如果相等,才会把内存中的值换成最终的值。如果内存中的值和期望的值不相等,说明其他线程已经对内存中的值发生改变。这时就不会操作成功。然后自旋,循环CAS操作。
java.util.concurrent.atomic(JUC)包下的类大多是使用 CAS 操作来实现的,比如 AtomicInteger、AtomicBoolean、AtomicLong。一般在竞争不是特别激烈的时候,使用该包下的原子操作性能比使用 synchronized 关键字高得多。
在较多的场景都可能会使用到这些原子类操作。一个典型应用就是计数,在多线程的情况下需要考虑线程安全问题。
CAS的缺点:
ABA 问题
ABA 问题说的是,如果一个变量第一次读取的值是 A,准备好需要对 A 进行写操作的时候,发现值还是 A,那么这种情况下,能认为 A 的值没有被改变过吗?可以是由 A -> B -> A 的这种情况,但是 AtomicInteger 却不会这么认为,它只相信它看到的,它看到的是什么就是什么。
可以采用CAS的一个变种DCAS来解决这个问题。DCAS,是对于每一个内存旧值V增加一个引用的表示修改次数的标记符count。对于每个内存旧值V,如果引用修改了一次,这个计数器count就加1。然后再这个变量需要update的时候,就同时检查变量的值和计数器的值(记录修改次数)。
循环开销大
我们知道乐观锁在进行写操作的时候会判断是否能够写入成功,如果写入不成功将触发等待 -> 重试机制,这种情况是一个自旋锁,简单来说就是适用于短期内获取不到,进行等待重试的锁,它不适用于长期获取不到锁的情况,另外,自旋循环对于性能开销比较大。
标签:CAS,旧值,并发,内存,自旋,操作,多线程 来源: https://www.cnblogs.com/hooong/p/14717785.html