Skip to main content

无锁宗师CAS

huhxAbout 2 minjavaConcurrency-ToolkitConcurrency

为了线程间共享数据的安全性,我们引入了锁的机制。不管是synchronized内置锁还是重入锁,在高并发时,对锁的激烈竞争导致的线程等待很大程度上会影响性能。为此,人们想到了一种称为非阻塞同步的方法,这种方式不需要锁。它,就是我们今天要讲的CAS

CAS

CAS全称Compare And Swape,是一种比较并交换的算法。在硬件层面上,大多数处理器架构中,是已经支持原子化的CAS指令的。在JDK 1.5之后,虚拟机就可以使用这个指令了。

CAS包含了3个操作数,它的形式为CAS(V, E, N)。其中V表示要更新的地址,E表示要比较的值,N表示新值。

  • 当V的值等于E时,V的值更新为N,返回的结果为V原有的值E
  • 当V的值不等于E时,说明有其它的线程做了更新,则当前线程就不做V值的更新。返回的结果是V的值

CAS的操作是乐观的,因为它总是希望自己能够成功的执行更新操作。

当多个线程尝试使用CAS更新同一个变量时,只有一个线程能够更新成功,其他线程都将更新失败。而且这些更新失败的线程并不会等待被挂起,而是被告知失败的结果。对于失败后的处理,线程可以自行处理。

线程在竞争CAS失败时不会阻塞,它可以决定是否重试,或者执行一些恢复操作,或者啥都不干直接退出。把这种竞争失败的处理交由给开发人员,这种灵活性就大大减少了与锁相关的活跃性问题了(死锁和优先级反转等等)。

原子操作

内存屏障?原子性是由硬件指令支持的,那内存的可见性呢?

工作原理

Unsafe

优缺点

ABA问题

循环长开销大

CAS的原子操作只能针对一个共享变量。

单个共享变量

FAQ

总结

参考