概念
CAS 是比较交换 CompareAndSwap 的简称,是一种用于在多线程环境下实现同步功能的机制。
顾名思义就是比较并交换。简单来说,从某一内存上取值 V,和预期值 A 进行比较
- 如果内存值 V 和预期值 A 的结果相等,那么我们就把新值 B 更新到内存;
- 如果不相等,说明在这个过程中这个值被别的线程修改果,那么就重复上述操作直到成功为止。
为什么要CAS
synchronized
在多线程中为了保持数据的准确性,避免多个线程同时操作某个变量,可以使用synchronized 实现同步锁。
使用 synchronized 关键字可以使操作的线程排队等待运行,可以说是一种悲观策略,认为线程会修改数据,所以开始就把持有锁的线程锁住,其他线程只能是挂起状态,等待锁的释放,所以同步锁带来了效率问题。
synchronized 的效率问题
在线程执行的时候,获得锁的线程在运行,其他被挂起的线程只能等待着持有锁的线程释放锁才有机会运行,时间浪费在阻塞等待上
在很多的线程切换的时候,由于有同步锁,就要涉及到锁的释放,加锁,这又是一个很大的时间开销。
volatile
与阻塞机制相比有一种更有效地方法,即非阻塞机制,同步锁带来了线程执行时候之间的阻塞,而这种非阻塞机制在多个线程竞争同一个数据的时候不会发生阻塞的情况,效率大大提升
使用 volatile 不会造成阻塞,volatile 保证了线程之间的内存可见性和程序执行的有序性可以说已经很好的解决了上面的问题。
volatile存在原子操作问题,volatile 不能保证原子性,对于复合操作
例如 i++ 这样的程序包含三个原子操作:取值,自增,赋值。这个过程在多线程执行的时候就会有数据不一致的问题
CAS的意义
- CAS(Compare And Swap 比较和交换)解决了 volatile 不能保证原子性的问题;
- CAS 操作即能够解决锁的效率问题,也能够保证操作的原子性。
CAS 操作原理
CAS 主要包含三个操作数,内存位置 V,原值 A,和新值 B。
- 当位置 V 的值与 A 相等时,CAS 才会通过原子方式用新值 B 来更新 V,
- 否则不会进行任何操作。无论位置 V 的值是否等于 A,都将返回 V 原有的值。
CAS 是一种乐观策略,每次都正常操作,不用担心其他线程会修改变量等数据,只在最后提交的时候验证数据是否被更改,如果其数据被更改,那么 CAS 会检测到并利用算法重新计算。
- CAS 也是同时允许一个线程修改变量,其他的线程试图修改都将失败;
- 相比于同步锁,CAS 对于失败的线程不会将他们挂起,下次仍可以继续提交,参与竞争,这也就是非阻塞机制的特点。
存在问题
ABA 问题
假设有两个线程,线程 1 和线程 2,线程 1 工作时间需要 6 秒,线程 2 工作需要 2 秒,主内存值为 A;