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

Java中不同显式synchronized锁下可变对象的修改可见性问题

问题解答

结论

setFeature对mFeature的修改不保证对useFeature可见。

原因说明

Java内存模型(JMM)中synchronized的可见性保证有明确的适用前提:只有同一个锁的解锁操作和后续的加锁操作之间才存在happens-before关系,也就是前一个线程释放锁之前的所有写入,对后一个拿到同一把锁的线程才可见。
你代码里两个同步块用的完全是不同的锁:

  • setFeature方法用的是FeatureService.class类对象作为全局锁
  • useFeature方法用的是每个FeatureService实例独立创建的MUTEX实例作为锁
    两者没有任何同步关联,所以不存在可见性保证,useFeature很可能读到的是旧的mFeature缓存值。

额外需要注意的是,mFeature是静态全局变量,而MUTEX是实例变量,就算不考虑setFeature的修改可见性,不同FeatureService实例调用useFeature时用的是不同的锁,互相之间也不会有互斥效果,同步逻辑完全失效。

修复建议

  • 方案1:把锁统一,要么都用FeatureService.class作为锁,要么把MUTEX也改成静态变量,两个方法都用这个静态锁
  • 方案2:如果只需要保证可见性不需要原子性,可以直接给mFeature加volatile修饰,跳过锁的可见性绑定限制
// 示例修复:统一用静态锁
public class FeatureService {
    private static Feature mFeature= null; 
    // 改成静态全局锁
    private static final Object MUTEX = new Object();
    ...

    static void setFeature(Feature feature){
        // doSomething
        synchronized (MUTEX){
            mFeature = feature;
            // doSomething
        }
        // doSomething
    }

    public void useFeature(...){
        // doSomething
        synchronized (MUTEX){
            someFunction(mFeature);
            // doSomething 
        }
        // doSomething
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:27:02