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

多线程场景下Java类的getValue是否需加synchronized?volatile是否必要?

问题分析与解答

首先给出你提交的代码示例:

public class A {
        private volatile int value = 0; // is volatile needed here?
    
        synchronized public void increment() { 
          value++; // Atomic is better, agree
        }
    
        public int getValue() { // synchronized needed ?
          return value;
        }
    }

核心结论

  • 如果你保持getValue()不加synchronized的现有写法:value的volatile修饰符必须保留,不需要额外给getValue()加synchronized
  • 如果你给getValue()加上synchronized:value的volatile修饰符可以去掉,不需要额外保留

原理说明

Java内存模型(JMM)的可见性规则要求:一个线程对共享变量的修改,必须能被其他线程及时读取到最新值,否则会出现脏读问题。

  1. 为什么无锁getValue()需要volatile
    synchronized的可见性保证只作用于加了同一把锁的同步块:increment()加了锁,退出同步块时会把value的修改刷新到主存,但无锁的getValue()不会主动从主存拉取最新值,可能会一直读到线程工作内存里缓存的旧值。而volatile修饰的变量会强制所有读操作直接从主存读取、写操作立即刷新回主存,刚好补上了这个可见性缺口。
  2. 为什么加锁getValue()不需要volatile
    如果getValue()也加了synchronized,那么读写方法都持有同一个A类实例的对象锁,根据Happens-Before规则:同一个锁的解锁操作,优先于后续对这个锁的加锁操作。所以increment()对value的修改,一定对后续拿到同一把锁执行的getValue()可见,不需要volatile额外保证可见性。

更优实现方案

建议直接用java.util.concurrent.atomic.AtomicInteger替代volatile int加synchronized的组合,高并发场景下性能更好,也不用手动处理同步逻辑:

public class A {
    private AtomicInteger value = new AtomicInteger(0);

    public void increment() {
        value.incrementAndGet();
    }

    public int getValue() {
        return value.get();
    }
}

内容的提问来源于stack exchange,提问作者J.J. Beam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:15:07