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

JMM是否保证synchronized写入对其他线程同步块后读取的变量可见?

JMM中synchronized块内写入的变量,对其他线程同步块后读取的可见性问题

我想确认JMM是否保证:一个线程在synchronized块内对变量的写入,对另一个线程在同一个监视器的synchronized块执行完成后读取对应变量的操作,具有可见性?

初始疑问示例代码

public class SynchronizedWriteRead {

    private int a;
    private int b;

    public void writer() {
        synchronized (this) {
            a = 5;
            b = 7;
        }
    }

    public void reader() {
        synchronized (this) {
            int r1 = a; /* 确定能读到5 */
        }
        int r2 = b; /* 是否能保证读到7? */
    }
}

对JMM规则的困惑

JMM明确规定,对一个监视器的解锁操作happens-before后续对该监视器的所有加锁操作,但我不确定这个规则是否仅局限于synchronized块内部的读写操作。

近期看到Aleksey Shipilëv的文章《Safe Publication and Safe Initialization in Java》中的描述:

注意在不安全的双重检查锁定(Unsafe DCL)中使用synchronized并无帮助,与外行认为它能神奇“刷新缓存”的想法相反。若读取受保护状态时没有配对的锁,则无法保证能看到锁保护的写入之前的操作。

正是这段内容让我产生了上述疑问,且我暂时没在JLS中找到明确答案。

对比volatile的可行方案

换个思路,我们可以借助volatile的happens-before保证实现类似的可见性效果,示例代码如下:

public class VolatileHappensBefore {

    private int a; /* 明确非volatile */
    private volatile int b;

    public void writer() {
        a = 5;
        b = 7;
    }

    public void reader() {
        int r1 = b; /* 能保证读到7 */
        int r2 = a; /* 能保证读到5 */
    }
}

这里的逻辑是:同一线程内的顺序操作满足happens-before,再加上happens-before的传递性,就能保证reader线程读取b之后,一定能看到writer线程对a的写入。

进一步的探索:借助synchronized的传递性?

那我们能不能用同样的逻辑,借助synchronized的happens-before保证实现类似效果?比如下面的代码(添加sync变量避免JVM优化移除空同步块):

public class SyncHappensBeforeTest {
    private int a;
    private int b;
    private int sync; // 用于避免空同步块被JVM移除

    public void writer() {
        a = 5;
        b = 7;
        synchronized (this) {
            sync = 1;
        }
    }

    public void reader() {
        synchronized (this) {
            int r = sync;
        }
        int r1 = a; /* 是否能保证读到5? */
        int r2 = b; /* 是否能保证读到7? */
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:45:32