线程学习笔记-AtomicStampReference

CAS引发的ABA问题
AtomicStampReference可以解决ABA问题

public class AtomicStampReferenceTest {
  private static AtomicStampedReference atomicRef = new AtomicStampedReference<Integer>(100,0);
  public static void main(String[] args)  throws InterruptedException{
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(1);
          boolean b = atomicRef.compareAndSet(100, 101, atomicRef.getStamp(), atomicRef.getStamp() + 1);
          System.out.println(b + "==="+atomicRef.getReference()+"==="+atomicRef.getStamp());
          boolean b1 = atomicRef.compareAndSet(101, 100, atomicRef.getStamp(), atomicRef.getStamp() + 1);
          System.out.println(b1 + "==="+atomicRef.getReference()+"==="+atomicRef.getStamp());
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });

    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          int stamp = atomicRef.getStamp();
          System.out.println("Before sleep:"+stamp);
          Thread.sleep(2);
          boolean b = atomicRef.compareAndSet(100, 101, stamp, stamp + 1);
          System.out.println(b+"");
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });
    t1.start();
    t2.start();
    t1.join();
    t2.join();
  }
}

当前值为100,戳为0
第一次期望值为100,期望戳为0,待更新值为101,戳为1,更新成功
此时当前值为101,戳为1
第二次期望值为101,期望戳为1,待更新值为100,戳为2,更新成功
此时当前值为100,戳为2
第三次期望值100,期望戳为0,待更新值为101,戳为1,更新失败
在这里插入图片描述
AtomicStampReference源码解析

    private static class Pair<T> {
    	// 当前值
        final T reference;
        // 当前版本
        final int stamp;
        private Pair(T reference, int stamp) {
            this.reference = reference;
            this.stamp = stamp;
        }
        static <T> Pair<T> of(T reference, int stamp) {
            return new Pair<T>(reference, stamp);
        }
    }

    private volatile Pair<V> pair;


    public boolean compareAndSet(V   expectedReference,
                                 V   newReference,
                                 int expectedStamp,
                                 int newStamp) {
        Pair<V> current = pair;	
        // 当前的值和版本都和期望值一样,且待更新的值和版本和当前的值和版本一样,返回true
        // 当前的值和版本都和期望值一样,且如果当前的pair和内存中的一样,则更新成功 
        return
            expectedReference == current.reference &&
            expectedStamp == current.stamp &&
            ((newReference == current.reference &&
              newStamp == current.stamp) ||
             casPair(current, Pair.of(newReference, newStamp)));
    }
	// 获取pair属性在内存中的偏移量
    private static final long pairOffset =
        objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);

    private boolean casPair(Pair<V> cmp, Pair<V> val) {
    	// cmp 代表当前的pair val代表待更新的pair
    	// 如果当前的pair和内存中的一样,则更新成功
        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
    }

    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
                                  String field, Class<?> klazz) {
        try {
            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
        } catch (NoSuchFieldException e) {
            // Convert Exception to corresponding Error
            NoSuchFieldError error = new NoSuchFieldError(field);
            error.initCause(e);
            throw error;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值