一文了解CAS
什么是CAS?
CAS全程:Compare And Swap(比较并交换),是乐观锁思想的一种体现,能在无锁的情况下保证线程安全。
Java中的CAS是由native方法实现的,底层通过硬件层面保证了CAS操作的原子性。
CAS是如何保证线程安全的?如下:
CAS操作会去比较工作内存中的旧值和内存中的预期值是否相等,相等才会将其改成新值。如下线程A来修改a,a旧值是100,去和主内存中的a比较,发现相等了,于是在工作内存进行a++操作并同步到主内存。
此时线程B也来修改a,但是旧值是100与主内存中101不相等,就会修改失败,CAS一般会搭配自旋,因此线程B会再次进行CAS,直至成功或者达到最大自旋次数。
CAS的优缺点?
CAS的优点就是无锁操作,线程不会阻塞,不用进行上下文切换,性能好。
缺点有ABA、循环时间过长性能开销、只能单变量原子性等问题。
ABA问题
ABA问题指如果一个值被修改了之后又被改回去了,那么CAS是无法发现值被修改了的。解决办法就是给数据加上一个版本号或者时间戳。
循环时间过长导致的性能开销
CAS自旋次数过多会给cpu带来很大的性能消耗。
解决思路是让 JVM 支持处理器提供的pause 指令。
pause 指令能让自旋失败时 cpu 睡眠一小段时间再继续自旋,从而使得读操作的频率降低很多,为解决内存顺序冲突而导致的 CPU 流水线重排的代价也会小很多。
只能保证单一变量的原子性
CAS操作无法保证多个变量的的原子性。
AtomicReference类保证对象的原子性,可以将多个变量放入对象中,对单一对象进行CAS操作。