package com.shi.CAS; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicStampedReference; /** * ABA Problem case * @author shiye * */ public class ABATest1 { static AtomicInteger auAtomicInteger = new AtomicInteger(100); static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1); public static void main(String[] args) throws InterruptedException { System.out.println("===============ABA Problem arising==============="); new Thread(()-> { boolean a1 = auAtomicInteger.compareAndSet(100, 200); System.out.println(Thread.currentThread().getName() + a1 + " The value after the first modification is " + auAtomicInteger.get()); boolean a2 = auAtomicInteger.compareAndSet(200, 100); System.out.println(Thread.currentThread().getName() + a2 + " The value after the second revision is " + auAtomicInteger.get()); },"thread A ").start(); new Thread(()-> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } boolean b1 = auAtomicInteger.compareAndSet(100, 2019); System.out.println(Thread.currentThread().getName() + b1 + " The value after the first modification is " + auAtomicInteger.get()); },"thread B ").start(); Thread.sleep(3000); System.out.println("===============ABA Problem solving==============="); new Thread(()->{ int stamp1 = atomicStampedReference.getStamp();//Get version System.out.println(Thread.currentThread().getName() + "The current version is: " + stamp1); try { Thread.sleep(1000);//Sleep 1s } catch (InterruptedException e) { e.printStackTrace(); } boolean C1 = atomicStampedReference.compareAndSet(100, 499, stamp1, stamp1+1); System.out.println(Thread.currentThread().getName() + C1 + " The value after the first modification is " + atomicStampedReference.getReference() + " Version number is: " + atomicStampedReference.getStamp()); int stamp2 = atomicStampedReference.getStamp();//Get version boolean C2 = atomicStampedReference.compareAndSet(499, 100, stamp2, stamp2+1); System.out.println(Thread.currentThread().getName() + C2 + " The value after the second revision is " + atomicStampedReference.getReference() + " Version number is: " + atomicStampedReference.getStamp()); },"thread C ").start(); new Thread(()->{ int stamp1 = atomicStampedReference.getStamp();//Get version System.out.println(Thread.currentThread().getName() + "The current version is: " + stamp1); try { Thread.sleep(3000);//Sleep 3s } catch (InterruptedException e) { e.printStackTrace(); } boolean d1 = atomicStampedReference.compareAndSet(100, 2019, stamp1, stamp1+1); System.out.println(Thread.currentThread().getName() + d1 + " The value after the first modification is " + atomicStampedReference.getReference() + " Version number is: " + atomicStampedReference.getStamp()); },"thread D ").start(); } }
Implementation results:
=============== The Generation of ABA Problem=============== Thread A true has a value of 200 after its first modification Thread A true has a value of 100 after the second modification The value of thread B true after the first modification is 2019 =============== The Solution of ABA Problem=============== The current version of thread C is:1 The current version of thread D is:1 The value of thread True after its first modification is 499 version number: 2 The value of thread C false after the second modification is 499 version number: 2 Thread D false has a value of 499 version number after the first modification: