Java并发编程之原子引用

一、AtomicReference

1. 核心功能

  • 原子更新对象引用:确保对引用变量的修改(如赋值、交换)是线程安全的。
  • 适用场景:单变量的原子操作,无需关心引用被修改的历史状态。

2. 代码示例:无锁栈实现

public class ConcurrentStack<T> {
    private AtomicReference<Node<T>> top = new AtomicReference<>();

    public void push(T item) {
        Node<T> newHead = new Node<>(item);
        Node<T> oldHead;
        do {
            oldHead = top.get();
            newHead.next = oldHead;
        } while (!top.compareAndSet(oldHead, newHead)); // CAS更新栈顶
    }

    public T pop() {
        Node<T> oldHead;
        Node<T> newHead;
        do {
            oldHead = top.get();
            if (oldHead == null) return null;
            newHead = oldHead.next;
        } while (!top.compareAndSet(oldHead, newHead)); // CAS弹出栈顶
        return oldHead.item;
    }

    private static class Node<T> {
        final T item;
        Node<T> next;
        Node(T item) { this.item = item; }
    }
}

3. 局限性

  • ABA问题:若引用从ABA,CAS无法感知中间状态变化,可能导致逻辑错误。

二、AtomicStampedReference

1. 核心功能

  • 解决ABA问题:通过关联一个int类型的版本号(Stamp),跟踪引用的修改次数。
  • 适用场景:需要严格检测引用是否被修改过的场景(如无锁链表、队列)。

2. 代码示例:ABA问题防护

public class ABADemo {
    private AtomicStampedReference<String> ref = 
        new AtomicStampedReference<>("A", 0); // 初始值"A",版本号0

    public void update() {
        int[] stampHolder = new int[1];
        String current = ref.get(stampHolder); // 获取当前值和版本号
        int newStamp = stampHolder[0] + 1;
        // 更新值并增加版本号
        ref.compareAndSet(current, "B", stampHolder[0], newStamp);
    }

    public boolean isModified() {
        return ref.getStamp() > 0; // 通过版本号判断是否被修改过
    }
}

3. 实现机制

  • 内部存储:一个对象引用 + 一个int版本号,两者绑定更新。
  • 原子操作:同时比较引用和版本号,确保二者均符合预期才更新。

三、AtomicMarkableReference

1. 核心功能

  • 简化状态追踪:通过一个boolean标记位记录引用是否被修改过。
  • 适用场景:仅需知道引用是否变化,无需精确版本号的场景(如资源状态标记)。

2. 代码示例:缓存失效标记

public class Cache<T> {
    private AtomicMarkableReference<T> data = 
        new AtomicMarkableReference<>(null, false); // 初始无数据,标记为未失效

    // 更新缓存并标记为有效
    public void updateCache(T newData) {
        data.set(newData, true); // 设置新数据,标记为有效
    }

    // 检查缓存是否有效(未被失效)
    public T getCache() {
        boolean[] markHolder = { false };
        T value = data.get(markHolder);
        return markHolder[0] ? value : null; // 仅返回有效数据
    }
}

3. 实现机制

  • 内部存储:一个对象引用 + 一个boolean标记位,两者绑定更新。
  • 原子操作:同时比较引用和标记位,确保二者均符合预期才更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值