CAS又称 自旋锁、无锁,是一种乐观锁
- compare and swap 的缩写 意为: 比较并交换 , 实现并发算法的常用技术 , 就是说我不用加锁 , 也能保证 ( 加锁会影响效率,可以考虑使用原子操作类 ) 原子性 , 当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试 , 因此可以知道 , CAS只会允许一个线程的执行成功
- CAS 包括三个操作数 - 内存位置 , 预期原值以及更新值
- 执行 CAS 操作的时候,将内存位置的值与预期原值比较
- 如果相匹配 , 那么处理器会自动的将该位置更新为新值
- 如果不匹配 , 处理器不做任何操作 , 多个线程同时执行 CAS 的操作只有一个成功
- 执行 CAS 操作的时候,将内存位置的值与预期原值比较
例如下面的 AtomicInteger 等 原子类 就是基于 CAS 实现的
操作的过程图解:
- CAS有三个操作数,位置内存值V , 旧的预期值A , 要修改的更新值B
- 当且仅当旧的预期值A 和内存值V相同时 , 将内存值V修改为B , 否则什么都不做或重来
AtomicInteger 执行过程源码:
AtomicInteger atomicInteger=new AtomicInteger();
public void addAtomic(){
atomicInteger.getAndIncrement();
}
// getAndIncrement方法 this是当前AtomicIntegr对象
// valueOffset是内存偏移量/值
// 1为自增量
// Unsafe类的getAndAddInt方法,该Unsafe类是在jdk里的rt.jar包
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
//var1对象里的var2这个内存偏移量的值
var5 = this.getIntVolatile(var1, var2);
//var1 AtomicInteger 对象本身
//var2 该对象值得引用地址,内存地址偏移量
//var4 需要变动的数量 +1
//var5 是用var1 var2 找出的主内存中真实的值
//用该 对象当前的值与var5比较
//如果相同,进行var5+var4并且返回true
//如果不同,继续从主内存中取值然后 再比较,直到更新完成
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
创建一个原子类对象 ( 默认初始化值为0 ) , 也可以传入定值 , 当我们使用CAS方法时 , 传入一个预期值 , 一个修改值 , 仅当预期值和当前对象 valueOffset的内存偏移量的值相同 , 就可以修改成功 , 前提是没有被其他的线程抢先一步进行比较并交换 , 否则就要继续读取最新的修改值 *( 变量可以使用 volatile关键字解决可见性问题 , 就是说 : 一个线程对共享变量的修改,能够及时的被其他线程看到 , 立刻同步最新数值 )* , 再继续的进行比较并交换这一操作 , 直到修改成功..... 这是比较并交换的源代码 : native为本地方法 , 底层用C 实现对操作系统的访问和操作 (Java不可以直接访问)