J.U.C 原子类系列之AtomicReference、AtomicStampedReference、AtomicMarkableReference

本文介绍了Java并发编程中的对象引用原子类,包括AtomicReference、AtomicStampedReference和AtomicMarkableReference。重点讨论了如何使用AtomicStampedReference和AtomicMarkableReference来解决ABA问题。文章通过示例说明了这两个类的工作原理,并提供了简单的场景模拟。
摘要由CSDN通过智能技术生成

简介

上一篇文章详细讲解了AtomicInteger原子类,还有和AtomicInteger原子类实现原理基本一样的AtomicLong和AtomicBoolean原子类。这些都是基本数据类型的原子类,在并发情景下可以保证基本数据类型变量的原子性。但是对于引用类型,这些基本类型的原子类就无能为力了,所以就出现对象引用类型的原子类

对象引用类型的原子类包括:AtomicReference、AtomicStampedReference、AtomicMarkableReference

AtomicReference原子类与基本数据类型的原子类实现过程相似,故不再赘述。

不过值得注意的是,使用CAS会有ABA的隐患!什么是ABA?知乎用户对ABA相关的提问

所以AtomicStampedReference、AtomicMarkableReference两个原子类就大派用场啦!

AtomicStampedReference 的使用

先看下AtomicStampedReference 原子类的核心源码:

public class AtomicStampedReference<V> {
   
    // Pair对象维护对象的引用和对象标志的版本,通过Pair对象解决“ABA”问题
    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 AtomicStampedReference(V initialRef, int initialStamp) {
    pair = Pair.of(initialRef, initialStamp); }

    public V getReference() {
    return pair.reference; }

    public int getStamp() {
    return pair.stamp; }

    public V get(int[] stampHolder) {
   
        Pair<V> pair = this.pair;
        stampHolder[0] = pair.stamp;
        return pair.reference;
    }

    public boolean weakCompareAndSet(V expectedReference,
                                     V newReference,
                                     int expectedStamp,
                                     int newStamp) {
   
        return compareAndSet(expectedReference, newReference,
                expectedStamp, newStamp);
    }

    /**
     * @param expectedReference 期待的原始对象
     * @param newReference      将要更新的对象
     * @param expectedStamp     期待原始对象的标志版本
     * @param newStamp          将要更新对象的标志版本
     */
    public boolean compareAndSet(V expectedReference,
                                 V newReference,
                                 int expectedStamp,
                                 int newStamp) {
   
        Pair<V> current = pair;
        return
                expectedReference == current.reference && // 如果返回true则说明期待的原始对象与Pair的reference对象一样
                        expectedStamp == current.stamp &&  // 如果返回true说明期待原始对象标志版本与Pair的stamp对象一样
                        ((newReference == current.reference &&
                                newStamp == current.stamp) || // 如果期待更新的对象和标志版本与Pair的reference和stamp一样的话直接返回true,否则执行CAS操作
                                casPair(current, Pair.of(newReference, newStamp))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值