多线程系列--CAS

其他网址

【死磕Java并发】----深入分析CAS_Java_chenssy的博客-CSDN博客

并发编程 CAS算法_Java_u014207606的博客-CSDN博客

简介

        CAS,Compare And Swap,即比较并交换。Doug lea大神在同步组件中大量使用CAS技术鬼斧神工地实现了Java多线程的并发操作,可以说CAS是整个JUC的基石。

CAS说明:

  • CAS是一种基于锁的操作,而且是乐观锁。
  • CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。若内存地址里面的值和A的值是一样的,就将内存里面的值更新成B。
  • CAS是通过无限循环来获取数据的,一旦检测到冲突产生,就重试当前操作直到没有冲突。若在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程自旋,直到某一次循环时地址里的值没有被修改。

以下组件都用到了CAS:

  • AQS同步组件
  • Atomic原子类操作
  • jdk8的ConcurrentHashMap使用CAS+Synchronized。

CAS缺点

主要表现在三个方面:CPU开销大;只能保证一个共享变量原子操作;ABA问题。

缺点 说明 解决方法
CPU开销大 如果自旋CAS长时间地不成功,则会给CPU带来非常大的开销。         在JUC中有些地方就限制了CAS自旋的次数,例如BlockingQueue的SynchronousQueue。
只能保证一个共享变量原子操作 CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。

        比如需要保证3个变量共同进行原子性的更新,就不得不使用Synchronized了。

        还可以考虑使用AtomicReference来包装多个变量,通过这种方式来处理多个共享变量的情况。

ABA问题 如果一个值原来是A,变成了B,然后又变成了A,那么在CAS检查的时候会发现没有改变,但是实质上它已经发生了改变,这就是所谓的ABA问题。在大部分情况下ABA问题并不会影响程序并发的正确性。

        即在每个变量都加上一个版本号,每次改变时加1,即A —> B —> A,变成1A —> 2B —> 3A。

        Java提供了AtomicStampedReference来解决。AtomicStampedReference通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题。

 

你可能感兴趣的:(Java多线程)