简单讲一下CAS

165 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

什么是CAS?

CAS: Compare And Swap,意为比较后替换,是无锁的解决方案,相对于synchronizedlock的重量级锁,CAS多应用于自旋锁这种轻量级锁,目的是通过非阻塞同步的方式来实现线程安全

执行流程

image.png

由图可得,当线程获取到一个新值B前会向内存中读取变量当前值A,在赋值时,对比A当前值C是否相等,若不相等,则代表在计算B值时,变量值已经被其他线程修改,已经不为A了,所以更新失败,保证了原子性

自旋锁的设计则是,当值更新失败时,反复尝试比较更新,直到更新成功,相对于重量级锁来说减少了性能开销,但是遇到极端情况自旋不停止的话就不如加锁来的实惠了

相关代码

Java中,提供了Unsafe类来执行内存操作等"不安全的"的方法和AtomicXXX等类来实现原子操作,这里主要讲一下AtomicInteger

下面是AtomicInteger提供的方法

public final int get(); //获取当前的值
public final int getAndSet(int newValue); //获取当前值并设置新的值
public final int getAndIncrement(); //获取当前值并自增
public final int getAndDecrement(); //获取当前值并自减
public final int getAndAdd(int delta); //获取当前值并加上delta
void lazySet(int newValue); //在一段时间后将值设置为newValue
/**
 * Atomically sets to the given value and returns the old value.
 *
 * @param newValue the new value
 * @return the previous value
 */
public final int getAndSet(int newValue) {
    return unsafe.getAndSetInt(this, valueOffset, newValue);
}

这是getAndSet()的源码,其中使用了Unsafe类提供的getAndSetInt()方法来设置value, valueOffset是值在内存中的偏移量,以此来找到值在内存中的实际地址

public final int getAndSetInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var4));

    return var5;
}

这是getAndSetInt()的源码,很明显的看见里面使用了CAS实现的自旋锁来进行赋值,若compareAndSwapInt()没有执行成功则反复执行,直到赋值成功

这就是AtomicInteger保证原子性的秘密