JavaにおけるCASの簡単な理解と使用


CAS(Compare And Swap)は比較して交換し、無ロックアルゴリズムであり、楽観的なロックであり、casを採用することでスレッドセキュリティの問題を実現することができる.CASには一般的に3つの値、メモリ値、予想元値、新しい値があり、メモリ値が予想元値と同じ場合にのみ修正を行うことができ、異なる場合には修正操作を行うことができない.
JUCパッケージの原子系操作はすべてCASで実現されており,同時コンテナ,スレッドプールなども多くCASで原子性操作を保証している.
しかしCASにもいくつかの問題があります:まずABA問題、循環が長すぎて資源を浪費して、
ABA問題の解決策は、元のパッケージの下にAtomicMarkableReference、AtomicStampedReferenceの2種類が提供されています.1つはbooleanに基づいて、AtomicMarkableReferenceはtrueまたはfalseで修正したかどうかを判断します(厳密にはこのクラスはABA問題を解決することはできませんが、確率を下げてtrue/falseでマークするだけです).AtomicStampedReferenceはバージョン番号メカニズムによってABAの問題を防止し、
class Test3 {
   static Product prudctor  = new Product(1,"zs");
     static AtomicReference atomicReference = new AtomicReference<>(prudctor);
   static AtomicMarkableReference markableReference = new AtomicMarkableReference<>(prudctor,true);
    static AtomicStampedReference stampedReference = new AtomicStampedReference<>(prudctor,1);
   public static void main(String[] args) {
        //==============AtomicReference===================
//        new Thread(()->{
//            //      ,  2 ,   B  ABA  
//            Product product=atomicReference.get();
//            System.out.println("  B     :"+product);
//            try {
//                TimeUnit.MILLISECONDS.sleep(2000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("  B   ABA        atomicReference:"+atomicReference.compareAndSet(prudctor, new Product(3, "ww")));
//        },"  A").start();
//        new Thread(()->{
//            //   A            
//            atomicReference.compareAndSet(atomicReference.get(),new Product(2,"ww"));
//            System.out.println("  A,      :"+atomicReference.get().toString());
//            atomicReference.compareAndSet(atomicReference.get(),prudctor);
//            System.out.println("  A,  aba           :"+atomicReference.get().equals(prudctor));
//        }).start();
       /**
        *     
        *   B     :Product{no=1, name='zs'}
        *   A,      :Product{no=2, name='ww'}
        *   A,  aba           :true
        *   B   ABA        atomicReference:true
        */
      //================   AtomicMarkableReference======
       new Thread(()->{
           //       ,  3 
           try {
               TimeUnit.SECONDS.sleep(2);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           Product reference = markableReference.getReference();

           markableReference.compareAndSet(markableReference.getReference(), new Product(2, "ww"), false, true);
           //         
           System.out.println("  B,  ABA  :"+markableReference.compareAndSet(markableReference.getReference(),reference, true, false));
       },"  B").start();

       new Thread(()->{
            //       ,  3 
            Product reference = markableReference.getReference();
            System.out.println("  A,      :"+reference);
            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("  A,   ABA          :"+
                    markableReference.compareAndSet(reference, new Product(2, "ww"), true, true));
        },"  A").start();
       /**
        *     
        *   A,      :Product{no=1, name='zs'}
        *   B,  ABA  :true
        *   A,   ABA          :false
        */

      //===============AtomicStamped===========
//       new Thread(()->{
//           //       A  stam
//           Product reference = stampedReference.getReference();
//           try {
//               TimeUnit.SECONDS.sleep(2);
//           } catch (InterruptedException e) {
//               e.printStackTrace();
//           }
////            ABA      A    
//           System.out.println(stampedReference.compareAndSet(reference, new Product(2, "ww"), stampedReference.getStamp(), stampedReference.getStamp() + 1));
//           //         
//           System.out.println("  B,  ABA  :"+stampedReference.compareAndSet(stampedReference.getReference(), reference, stampedReference.getStamp(), stampedReference.getStamp()+1));
//       },"  B").start();
//       new Thread(()->{
//           //       ,  3 
//           int stamp = stampedReference.getStamp();
//           System.out.println("   :"+stamp);
//           try {
//               TimeUnit.SECONDS.sleep(2);
//           } catch (InterruptedException e) {
//               e.printStackTrace();
//           }
//           System.out.println("  A,   ABA          :"+ stampedReference.compareAndSet(stampedReference.getReference(), new Product(2, "ww"),stamp,stamp+1));
//       },"  A").start();
       /**
        *        
        *    :1
        * true
        *   B,  ABA  :true
        *   A,   ABA          :false
        */
   }
}