J.U.C之CAS

线程double

记录下

什么是CSA?

CAS(compare And Swap),即比较并交换,用来解决多线程并行情况下使用锁造成性能损耗的一种机制。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。它是 java.util.concurrent.atomic 包的基础。

实现了CAS的有原子类(AtomicInteger, AtomicLong, 等等原子类)

CAS 是乐观锁,一种高效实现线程安全性的方法,支持原子更新操作,适用于计数器,序列发生器等场景。属于乐观锁机制,号称 lock-free(无锁并发),在操作失败时由开发者决定是继续尝试还是执行别的操作,因此征用失败的线程不会被阻塞挂起。

CAS 具体的思想是包含三个操作数,内存位置(V)、预期原值(A)和新值(B),执行CAS操作时将内存位置的值与预期原值进行比较,如果相匹配那么处理器将该位置的值更新为新值,否则不进行任何操作(这里内存位置的值是主内存的值)。

CAS 多数情况下对开发者来说是透明的,J.U.C 的 atomic 包提供了常用的原子性数据类型以及引用、数组等相关原子类型和更新操作工具,是很多线程安全程序的首选,Unsafe类虽提供 CAS 服务,但因能操作任意内存地址读写而有隐患。

CAS实现

主要依赖 AtomicReference 类提供一个可以原子读写的对象引用变量,原子意味着多个线程更改相同 AtomicReference 最终达到一致的状态,AtomicReference 有一个先进的 compareAndSet() 方法。查看更多

CAS 缺点

  • 若循环时间长,则开销很大
  • 只能保证一个共享变量的原子操作
  • ABA问题(处理器进行 v 比较时,无法确认该值是否被其他线程改动过,然后又被其他线程改回来),J.U.C 为了解决这个问题提供了带有标记原子引用位(AtomicStampedReference) 它可以知道变量中途变更了几次,但有时候我们并不关心变量中途更改几次,只单纯的关心是否更改,这时我们就可以使用 AtomicMarkableReference,两者的区别就是不在引用 int 标识引用,而是使用 boolean 变量–表示引用变量是否被更改过。

参考文章

Java中的自旋锁实现
深入浅出CAS
CAS和AQS
BATJ都爱问的多线程面试题