多线程之CAS

多线程之CAS

CAS

CAS(Compare And Swap) 是乐观锁的一种实现方式。

  • 内存位置 (V)
  • 预期原值 (A)
  • 新值 (B)

当且仅当预期值A与内存值V相同,将内存值修改为B,否则什么都不做。

Screen Shot 2020-08-15 at 5.33.40 PM

AtomicInteger

  • getAndIncrement
  • getAndDecrement
  • incrementAndGet
  • decrementAndGet

Java Atomic 包 使用乐观锁中的CAS。

eg: AtomicInteger#getAndIncrement

// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}

private volatile int value;

# Unsave
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;
}


Unsafe提供了一些对底层的操作,通过JDI(Java Native Interface) 本地调用C/C++语言来实现CAS操作的。

do while循环,从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。

CAS的问题:

  1. 多线程场景下会出现ABA问题
  2. 循环(自旋)时间长开销大,如果CAS操作失败,就需要循环进行CAS操作(循环同时将期望值更新为最新的),如果长时间都不成功的话,那么会造成CPU极大的开销。
  3. 只能保证一个共享变量的原子操作, 如果需要对多个共享变量进行操作,可以使用加锁方式(悲观锁)保证原子性,或者可以把多个共享变量合并成一个共享变量进行CAS操作。

ABA问题

有2个线程同时对同一个值(初始值为A)进行CAS操作,这三个线程如下

  1. 线程1,期望值为A,欲更新的值为B
  2. 线程2,期望值为A,欲更新的值为B

线程1抢先获得CPU时间片,而线程2因为其他原因阻塞了,线程1取值与期望的A值比较,发现相等然后将值更新为B,然后这个时候出现了线程3,期望值为B,欲更新的值为A,线程3取值与期望的值B比较,发现相等则将值更新为A,此时线程2从阻塞中恢复,并且获得了CPU时间片,这时候线程2取值与期望的值A比较,发现相等则将值更新为B,虽然线程2也完成了操作,但是线程2并不知道值已经经过了A->B->A的变化过程。

ABA解决问题:

添加版本号,在变量前面加上版本号,每次变量更新的时候变量的版本号都+1,即A->B->A就变成了1A->2B->3A

AtomicStampedReference 类使用版本号作比较的CAS机制。

CAS VS Synchronized

性能差别: synchronized属于悲观锁,没有获得锁的线程会进入blocked状态,然后获取锁后恢复为runnable,涉及到用户模式和内核模式的转换,代价较高。

Reference

https://mp.weixin.qq.com/s/f9PYMnpAgS1gAQYPDuCq-w

https://mp.weixin.qq.com/s/nRnQKhiSUrDKu3mz3vItWg

https://mp.weixin.qq.com/s/yuokP0GtPRFc5UWxecrcJg

https://mp.weixin.qq.com/s/vNJYL_rL02wVTB6pvtvmJQ

https://mp.weixin.qq.com/s?__biz=MzIxMzk3Mjg5MQ==&mid=2247483688&idx=1&sn=675cf4b17021c952ce2fd778b8456b78&chksm=97afe3dca0d86aca38a161ea01c3de07692ae2938326d094836240c26dd99ab3411750cafeb8&scene=21#wechat_redirect

https://mp.weixin.qq.com/s/3ATJIXB9rQcNZug9KAHtOQ