目录
什么是 CAS
CAS 是怎么实现的
CAS 有哪些应用
1. 实现原子类
2. 实现自旋锁
3. CAS 的 ABA 问题
什么是 CAS
// 能够比较和交换某个寄存器中的值和内存中的值, 看是否相等, 如果相等, 则把另一个寄存器中的值和内存中的值进行交换
// CAS伪代码
java">boolean CAS(address, expectValue, swapValue) {
if (&address == expectedValue) {
&address = swapValue;
return true;
}
return false;
}
// CAS 其实是由一个原子的硬件指令完成的 (原子性)
// 当多个线程同时对某个资源进行 CAS 操作, 只能有一个线程操作成功. 但是并不会阻塞其他线程, 其他线程只会收到操作失败的信号
// CAS 可以视作是一种乐观锁(或者说 CAS 是乐观锁的一种实现方式)
// 基于CAS 又衍生出一套 "无锁编程"
CAS 是怎么实现的
// 针对不同的操作系统, JVM 用到了不同的 CAS 实现原理, 简而言之 : 是因为硬件给予了支持, 软件层面才能做到
CAS 有哪些应用
1. 实现原子类
// 标准库中提供了 java.util.concurrent.atomic 包, 里面的类都是基于这种方式来实现的.典型的就是Atomiclnteger 类, 其中的 getAndIncrement 相当于 i++ 操作
java">AtomicInteger atomicInteger = new AtomicInteger(0);
// 相当于 i++
atomicInteger.getAndIncrement();
1.1 伪代码实现
java">class AtomicInteger {
private int value;
public int getAndIncrement() {
int oldValue = value;
while ( CAS(value, oldValue, oldValue+1) != true) {
oldValue = value;
}
return oldValue;
}
}
2. 实现自旋锁
// 自旋锁伪代码
java">public class SpinLock {
private Thread owner = null;
public void lock() {
while(!CAS(this.owner, null, Thread.currentThread())) {
}
}
public void unlock() {
this.owner = null;
}
}
3. CAS 的 ABA 问题
// CAS 关键要点, 是比较 寄存器1 和 内存 的值, 通过这里的是否相等, 来判定 内存的值 是否发生了改变. 如果内存的值变了, 存在其他线程进行了修改; 如果内存的值没变, 没有别的线程修改, 接下来进行的修改就是安全的
// 如果这里的值没变, 就一定没有别的线程修改嘛?
// A-B-A : 另一个线程, 把变量的值从 A -> B, 又从 B -> A , 此时本线程区分不了, 这个值是始终没变, 还是变化又回来了的情况
// 大部分情况下, 就算出现 ABA 问题, 也没啥太大影响, 但是如果遇到一些极端场景下就会出现问题
// 如果约定, 值只能单向变化, 增加一个版本号这个新的属性, 让版本号只能增长不能减小, 只要数据修改, 版本号就一定要增加, 这时我们只需要判定版本号是否相等, 若相等就是数据没有被修改
// 实际开发中, 一般不会直接使用 CAS, 都是用 库里已经封装好的组件(像原子类这种)