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

Vavr中Lazy类基于volatile supplier的双重检查锁定为何线程安全

关于Vavr Lazy实现的线程安全性解答

这段代码完全符合JSR-133内存模型规范,不存在你担心的半初始化对象逃逸问题,核心逻辑如下:

  • 首先明确get()方法的执行逻辑:只有当读supplier(volatile变量)的结果为null时,才会直接读取value返回,否则都会进入同步方法computeValue。
  • 我们先看computeValue内部的重排序约束:给supplier赋值null是volatile写操作,根据JMM重排序规则,volatile写之前的所有读写操作(包括s.get()内部的对象初始化、给value赋值的操作),都不允许被重排序到volatile写之后。也就是说,必须等对象完全初始化、value赋值完成后,才会执行supplier = null的操作。
  • 再看读侧的可见性保障:根据JMM的happens-before规则,对volatile变量的写操作,happen-before于后续对这个变量的读操作。也就是说,当其他线程在get()中读到supplier == null时,写supplier之前的所有操作(对象初始化、value赋值)对当前线程都是可见的,此时读到的value一定是完全初始化后的对象。
  • 你担心的对象初始化和value赋值的重排序问题,并不会导致半初始化对象逃逸:因为这种重排序只会发生在supplier被置为null之前,此时其他线程读supplier的结果都是非null,会进入同步方法computeValue,而computeValue被synchronized修饰,同一时间只有一个线程能进入,其他线程会阻塞等待首个执行线程完成初始化、将supplier置为null后才会继续执行,不会出现直接读取半初始化value的场景。

你提到的注释中说value表现得像volatile,本质就是依赖volatile读写的happens-before规则,把对value的读写和supplier的volatile读写绑定,从而获得可见性和有序性保障。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:09:03