CAS 指的是目前 CPU 中广泛支持的一种对内存中的共享数据进行操作的特殊指令,这个指令会对内存中的共享数据进行原子性操作。
CAS 操作过程
CPU 会将内存中将要被更改的数据与期望值做比较,相同则将内存中的值替换成新的值,否则不做操作,最后 CPU 将原来的旧值返回。其中这一系列操作是原子的。
CAS 含义:“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少”。
CAS 原理图
分析:图中有三个参数
- V 表示要更新的变量
- E 表示期望值(旧值)
- N 表示新值
V 变量是线程从内存中获取到的值,E 变量是自定义的值,N 变量是条件成立后会修改的值。
代码示例
首先看一个简单的示例:
if (xxx) {
a = a + 1;
}
如果在做 a = a + 1 之前 a 的值被其它线程修改了则会发生问题。因为该操作分为三个子步骤进行,不是原子性。这时可以采用锁解决此问题,但锁机制会带来上下文切换开销,CAS 也可以解决此问题,代码如下:
int V = A;
if (A.compareAndSet(V, A + 1)) {
xxx
} else {
xxx
}
这样的话一旦 A 的值被修改 A + 1 就不会执行了。
但是上面代码判断一次之后就结束了,如果还想执行 A + 1 操作就需要使用 for(;;) 无限循环,代码如下:
for (;;) {
int V = A;
if (A.compareAndSet(V, A + 1)) {
xxx
return;
} else {
xxx
}
}
ABA 问题
简单理解:就是生活中的掉包,小偷看上你的真皮钱包,他用一个假的钱包(外观一模一样)趁你不注意换了你的钱包,你并不会有察觉。
标准解释:ABA 问题也就是发生 a++ 之间,a 的值可能被多个线程修改,不过最后都回到了最初的值,但 CAS 会认为 a 的值并没有改变。