本文最后更新于:2022年6月11日 下午
                  
                
              
            
            
              
              CAS 
CAS,Compare And Swap,即比较并交换。整个AQS同步组件(例:ReentrantLock获取锁的时候)、Atomic原子类操作等等都是以CAS实现的,ConcurrentHashMap在1.8的版本中也调整为了CAS+Synchronized。 
 
定义 
在CAS中有三个参数:内存值V、旧的预期值A、要更新的值B,当且仅当内存值V的值等于旧的预期值A时才会将内存值V的值修改为B,否则什么都不干。
ReentrantLock获取锁(AtomicInteger也用到了):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 final  void  lock ()  {if  (compareAndSetState(0 , 1 ))else 1 );final  void  lock ()  {1 );private  static  final  Unsafe  unsafe  =  Unsafe.getUnsafe();private  static  final  long  stateOffset;protected  final  boolean  compareAndSetState (int  expect, int  update)  {return  unsafe.compareAndSwapInt(this , stateOffset, expect, update);public  final  native  boolean  compareAndSwapInt (Object var1, long  var2, int  var4, int  var5) ;
Unsafe是CAS的核心类,提供了硬件级的原子操作,Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。
CAS的缺点 如果自旋CAS长时间地不成功,则会给CPU带来非常大的开销。在JUC中有些地方就限制了CAS自旋的次数,例如BlockingQueue的SynchronousQueue。也可以自己设置可以使用-XX:PreBlockSpin来更改。
ABA问题,解决方案则是版本号,Java提供了AtomicStampedReference来解决。Pair为AtomicStampedReference的内部类,主要用于记录引用和版本戳信息(标识)。版本戳为int型,保持自增。同时Pair是一个不可变对象,其所有属性全部定义为final,对外提供一个of方法,该方法返回一个新建的Pari对象。pair对象定义为volatile,保证多线程环境下的可见性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 class  Test  {private  static  AtomicInteger  atomicInt  =  new  AtomicInteger (100 );private  static  AtomicStampedReference  atomicStampedRef  =  new  AtomicStampedReference (100 , 0 );public  static  void  main (String[] args)  throws  InterruptedException {Thread  intT1  =  new  Thread (new  Runnable () {@Override public  void  run ()  {100 , 101 );101 , 100 );Thread  intT2  =  new  Thread (new  Runnable () {@Override public  void  run ()  {try  {1 );catch  (InterruptedException e) {boolean  c3  =  atomicInt.compareAndSet(100 , 101 );Thread  refT1  =  new  Thread (new  Runnable () {@Override public  void  run () try  {1 );catch  (InterruptedException e) {100 , 101 , atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1 );101 , 100 , atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1 );Thread  refT2  =  new  Thread (new  Runnable () {@Override public  void  run ()  {int  stamp  =  atomicStampedRef.getStamp();try  {2 );catch  (InterruptedException e) {boolean  c3  =  atomicStampedRef.compareAndSet(100 , 101 , stamp, stamp + 1 );
只能保证一个共享变量的原子操作,Java从1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,可以把多个变量放在一个对象里来进行CAS操作。