AtomicStampedReference通过版本戳stamp解决ABA问题
各种乐观锁的实现中通常都会用版本戳version来对记录或对象标记,避免并发操作带来的问题,在Java中,AtomicStampedReference<E>也实现了这个作用,它通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题,例如下面的代码分别用AtomicInteger和AtomicStampedReference来对初始值为100的原子整型变量进行更新,AtomicInteger会成功执行CAS操作,而加上版本戳的AtomicStampedReference对于ABA问题会执行CAS失败:
1 import java.util.concurrent.TimeUnit; 2 import java.util.concurrent.atomic.AtomicInteger; 3 import java.util.concurrent.atomic.AtomicStampedReference; 4 5 6 public class TestABA { 7 8 private static AtomicInteger atomicInt = new AtomicInteger(100); 9 private static AtomicStampedReference atomicStampedRef = new AtomicStampedReference(100, 0); 10 11 public static void main(String[] args) throws InterruptedException { 12 Thread intT1 = new Thread(new Runnable() { 13 @Override 14 public void run() { 15 atomicInt.compareAndSet(100, 101); 16 atomicInt.compareAndSet(101, 100); 17 } 18 }); 19 20 Thread intT2 = new Thread(new Runnable() { 21 @Override 22 public void run() { 23 try { 24 TimeUnit.SECONDS.sleep(1); 25 } catch (InterruptedException e) { 26 } 27 boolean c3 = atomicInt.compareAndSet(100, 101); 28 System.out.println(c3); // true 29 } 30 }); 31 32 intT1.start(); 33 intT2.start(); 34 intT1.join(); 35 intT2.join(); 36 37 Thread refT1 = new Thread(new Runnable() { 38 @Override 39 public void run() { 40 try { 41 TimeUnit.SECONDS.sleep(1); 42 } catch (InterruptedException e) { 43 } 44 atomicStampedRef.compareAndSet(100, 101, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1); 45 atomicStampedRef.compareAndSet(101, 100, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1); 46 } 47 }); 48 49 Thread refT2 = new Thread(new Runnable() { 50 @Override 51 public void run() { 52 int stamp = atomicStampedRef.getStamp(); 53 try { 54 TimeUnit.SECONDS.sleep(2); 55 } catch (InterruptedException e) { 56 } 57 boolean c3 = atomicStampedRef.compareAndSet(100, 101, stamp, stamp + 1); 58 System.out.println(c3); // false 59 } 60 }); 61 62 refT1.start(); 63 refT2.start(); 64 } 65 66 }
浙公网安备 33010602011771号