You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AtomicReference实现延迟初始化是否具备线程安全性?

AtomicReference实现延迟初始化的线程安全性验证

我们团队在讨论用AtomicReference实现延迟初始化的线程安全性时产生了争议:有同事认为首批执行的线程可能获取到null值,导致初始化失败。为此我写了如下测试代码——拆分get与compareAndSet操作是为了避免每次调用开销较高的costlyGetValue()方法,测试从未失败,想确认这个实现是否真的安全。

public class TestAtomicReference {
    static final AtomicReference<String> A = new AtomicReference<>();

    public static void main(String[] args) throws Exception {

        Callable<Integer> callable = () -> {
            lazyInit();
            return 0;
        };

        ExecutorService executorService = Executors.newFixedThreadPool(50);

        for (int i = 0; i < 1000; i++) {
            A.set(null);
            List<Future<Integer>> futures = executorService.invokeAll(Collections.nCopies(50, callable));
            futures.forEach(f -> {
                try {
                    f.get();
                } catch (Exception ignore) {
                }
            });
        }

        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.SECONDS);
    }

    private static void lazyInit() {
        if (A.get() == null) {
            A.compareAndSet(null, costlyGetValue());
        }

        if (A.get() == null) {
            System.out.println("INIT FAILURE!");
        }
    }

    private static String costlyGetValue() {
        return "A";
    }
}

这个实现是线程安全的,绝不会出现初始化失败(即打印"INIT FAILURE!")的情况,原因如下:

  • AtomicReference的get()和compareAndSet()都是原子操作,且JVM保证这些操作的内存可见性:一个线程对AtomicReference的修改,其他线程能立即读取到最新值。
  • 当多个线程同时进入lazyInit():
    1. 第一个执行A.get()的线程会发现值为null,进而执行compareAndSet(null, costlyGetValue()),成功将A的值设置为"A"。
    2. 后续线程不管是在第一个线程完成CAS前还是后进入第一个if判断,当它们执行第二个A.get()时,结果必然不为null:要么A已经被第一个线程设置完成,要么自己执行CAS时发现A已经有值(CAS失败),但此时A的最新值已经存在。
  • 就算多个线程同时调用costlyGetValue(),在当前测试里只是多生成了几个相同的字符串(字符串常量池会复用,实际额外开销极小),但最终只有一个线程能CAS成功,其他线程的CAS失败不会影响A的最终状态。

需要注意的是:如果costlyGetValue()是带有副作用的方法(比如创建独占资源、修改全局状态),那么这种实现会导致该方法被多次调用——如果不能接受这种情况,可能需要搭配同步块来控制;但如果只是单纯开销高但无副作用,这个实现完全可以放心使用。

内容的提问来源于stack exchange,提问作者PZ73

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 05:22:26