一、CAS介绍
CAS(Compare and Swap),即比较-交换操作,是一种原子操作。原子操作是指不可中断的一个或一系列操作。这个操作被看做是一个整体,不可能被线程调度机制打断,保证了并发安全性。其中CAS是一种基于硬件实现的操作,可以实现不加锁的并发安全。
CAS一般包括三个操作数:内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。整个比较和交换操作是一个原子操作。
二、CAS的应用
CAS主要应用于多线程并发操作中,例如在Java中,常用的Atomic系列类,就是使用CAS实现的原子操作类,如下所示:
public class AtomicInteger { private volatile int value; public AtomicInteger(int value) { this.value = value; } public final int get() { return value; } public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } }
上面代码中的getAndIncrement()方法就是使用CAS实现的原子操作,其实现方式可以简单描述为:
- 获取当前值(current)
- 计算新的值(next)
- 使用CAS更新值,如果更新成功,则返回当前值
- 如果更新失败,则重新获取当前值进行下一次操作
三、CAS的优缺点
优点
- 无锁化并发编程,避免了锁的开销
- 确保了并发条件下的数据一致性和正确性
- 可以减少内存的使用,提高内存效率
- 可扩展性比锁高,可以有效避免死锁问题
缺点
- CAS操作的ABA问题:如果位置V一开始是A,后来被改为B,然后又被改回为A,那么CAS会认为它从来没有被修改过。解决方式可以加上版本号,每次修改都会将版本号+1。
- CAS操作只能保证一个共享变量的原子操作,对多个共享变量的操作必须加锁
- CAS操作失败的开销比较大,包括循环时间、CPU消耗等资源的消耗,如果CAS机制适用的情景是非常重要的
四、CAS的实现
下面给出一个CAS的简单实现,用于说明CAS的原理:
public class ThreadSafeCounter { private volatile int count; public int getCount() { return count; } public void increment() { int oldValue = count; while (!compareAndSet(oldValue, oldValue + 1)) { oldValue = count; } } public boolean compareAndSet(int oldValue, int newValue) { if (count == oldValue) { count = newValue; return true; } return false; } }
上面代码中的increment()方法使用了CAS实现的原子操作,其实现方式可以简单描述为:
- 获取当前值oldValue
- 如果使用CAS更新值失败,则重新获取当前值oldValue
- 重复执行第二步,直到更新成功
五、总结
CAS作为一种基于硬件实现的操作,可以实现不加锁的并发安全,常见的应用场景是多线程并发操作。虽然CAS有其优势和缺点,但是在特定的场景下,可以有效地提高代码的效率和性能。