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

volatile关键字作用解析:为何添加后1,0输出情况不复存在?

编译器重排序与Volatile的内存语义解析

原始代码(无Volatile)

class OrderingTest {
   var x = 0
   var y = 0
   fun test() {
       thread {
           x = 1
           y = 1
       }
       thread {
           val a = y
           val b = x
           println("$a, $b")
       }
   }
}

原始代码的四种可能输出

1,0
0,1
0,0
1,1

修改后代码(给y添加@Volatile)

class OrderingTest {
   var x = 0
   @Volatile var y = 0
   fun test() {
       thread {
           x = 1
           y = 1
       }
       thread {
           val a = y
           val b = x
           println("$a, $b")
       }
   }
}

为什么添加@Volatile后1,0的输出不可能?

要搞懂这个问题,得抓住@Volatile的两个核心内存语义:

  • 禁止指令重排序:针对写volatile变量的操作,JVM会保证在它之前的所有普通变量写操作,不能被重排到它之后执行。
  • 内存可见性:写volatile变量时,会把之前所有变量的修改同步到主内存;读volatile变量时,会强制从主内存读取,并且能看到所有在写这个volatile变量之前的修改。

具体到这段代码:

  1. 对于第一个线程的x=1和y=1:
    因为y是volatile变量,JVM会强制x=1的执行顺序在y=1之前,绝对不会出现先写y=1再写x=1的情况。而且当y=1被写入主内存时,x=1的修改也会同步到主内存。
  2. 对于第二个线程的val a = y和val b = x:
    当第二个线程读到a=1(也就是y=1)时,根据volatile的内存可见性规则,它必然能看到第一个线程在写y=1之前完成的所有修改——也就是x=1。所以此时读取x得到的b一定是1,不可能出现a=1但b=0的情况。

所以添加@Volatile后,1,0的输出就彻底被排除了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 08:36:52