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

线程同步块未退出时,其他线程读变量是否需加volatile?

问题描述

现有类A的代码如下:

class A
{
  int var;

  void method()
  {
    read(var);

    synchronized (this) {
      // 在这里更新var的值
      var = ...;
    }
  }
}

假设场景:线程1获取锁进入同步块,更新了var的值(该值可能缓存于处理器核心中),且线程1仍未退出同步块。此时线程2启动并进入method()读取var的值,请问:

  1. 线程2必然能获取到更新后的值吗?
  2. synchronized是否能保证线程2获取到更新值?
  3. 这种情况下是否需要将var声明为volatile?
    注:所有操作针对同一对象。
问题解答
  • 线程2不一定能获取到更新后的值
    线程1在同步块内更新var后,只要没退出同步块,就不会触发synchronized的内存可见性语义——只有线程退出同步块时,才会把工作内存中的修改刷新到主内存;其他线程进入同一个锁的同步块时,才会强制从主内存读取最新值。而线程2的读操作在同步块外,既没有获取锁的动作,也不会触发主内存读取,所以它读到的可能是自己工作内存里的旧值,或者主内存中未被线程1刷新的旧值。

  • synchronized不能保证线程2获取到更新值
    synchronized的内存可见性规则是:线程退出同步块时的修改,对后续进入该同步块的线程可见。但线程2的读操作不在同步块内,且线程1还没退出同步块,所以synchronized的可见性机制在这里不生效。线程1的修改还停留在自己的工作内存中,没有同步到主内存,线程2无法保证读到最新值。

  • 这种情况下需要将var声明为volatile
    如果希望线程2在同步块外读取var时,能看到线程1在同步块内的实时修改,就需要给var加上volatile修饰。volatile会强制所有线程直接从主内存读写变量,禁止线程缓存变量副本,这样线程1对var的修改会立即刷新到主内存,线程2读取时也会直接获取最新值。当然,如果线程2的读操作也放到同一个同步块内,不加volatile也能保证可见性,但如果读操作必须在同步块外,volatile就是必要的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:54:20