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

Java内存模型重排:JCStress测试未出现(1,0)结果的原因探究

为什么JCStress测试中从未出现(1,0)的结果?

先看你的测试代码:

@JCStressTest 
@Outcome(id = "1, 1", expect = Expect.ACCEPTABLE, desc = "ordered") 
@Outcome(id = "0, 1", expect = Expect.ACCEPTABLE, desc = "ordered") 
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE, desc = "reordered") 
@Outcome(id = "0, 0", expect = Expect.ACCEPTABLE, desc = "ordered") 
@State 
public class TestJUC {
     private int x;

    public TestJUC() {}

    @Actor
    public void actor1() {
     x = 1;
    }

    @Actor
    public void actor2(II_Result r) {
        int a = x;
        r.r1 = a;

        int b = x;
        r.r2 = b;
    }
}

你提到理论上actor2的语句可以重排成先读b再读a,进而产生(1,0)的结果,但实际测不出来,核心原因是你大概率在x86架构的机器上跑测试,而x86的内存模型不允许这种重排:

  • x86采用TSO(全存储顺序)内存模型,对内存操作的重排有硬限制:读操作不能被重排到更早的读操作前面,也就是actor2里两次读x的顺序必须和代码编写顺序一致——先读a,再读b。
  • 这样一来,只会出现三种结果:
    1. actor1完全未执行:两次读x都得到0,结果为(0,0);
    2. actor1在actor2读a之后、读b之前执行:a为0,b为1,结果为(0,1);
    3. actor1在actor2开始前就执行完毕:两次读x都得到1,结果为(1,1)。
  • 你设想的先读b(读到0)、再让actor1写x=1、最后读a(读到1)的场景,在x86架构下根本不可能发生,因为处理器不会重排这两个读操作的顺序。

如果换用ARM、PowerPC这类弱内存模型的架构运行测试,确实有可能观测到(1,0)的结果——这些架构允许更多内存操作重排。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:35:07