java的CAS原理

what:

  CAS的全称是Compare and Swap,即比较并交换。比较的是当前内存中存储的值与预期原值,交换的是新值与内存中的值。这个操作是硬件层面的指令,因此能够保证原子性。Java通过JNI(本地方法调用)来使用这个原子操作,也是乐观锁最常用的机制

 

  CAS操作包含三个操作数——内存位置、预期原值和新值。在执行CAS操作时,先进行Compare操作,即比较内存位置的值与预期原值是否相等,若相等,则执行Swap操作将新值放入该内存位置。若不相等,则不进行Swap操作。demo如下:

 

   

  UnSafe类中的重要方法,都是native的,是调用了底层操作系统的CAS指令,如下:

 

 

where(使用场景)

  在Java的concurrent包中,有一种通用的实现方式,即CAS配合volatile来实现许多高并发类。

 

 

 

how(缺陷的解决方案):

  1、ABA问题:

    value初值为A,线程1读取到预期原值为A,线程2读取到预期原值为A,线程1通过CAS操作将A更新为B,再通过一次CAS操作将值更新为A,此时线程2进行CAS操作,在比较时发现预期原值A与当前内存位置的值A相同,则进行更新,但是此时value已经被更新过了,而不是原来那个A值了,这样会产生线程安全问题。

    现在也有解决方案,在Java API中有一个类为AtomicStampedReference,该类在记录预期原值的同时还会记录标志,在比较时还会比较标志。

 

 

  2、自旋时间长的情况下会导致很大开销。

    若JVM支持pause指令,则可以解决此问题。pause指令有两个作用,第一是延迟流水线执行指令,使得CPU不会消耗太多执行时间;第二是避免在退出循环时因内存顺序冲突而引起CPU流水线被清空。

 

posted @ 2022-06-01 18:08  修心而结网  阅读(408)  评论(0编辑  收藏  举报