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

线程中final字段冻结语义疑问:构造器修改后hb关系与f.y可见性

关于final字段与happens-before顺序的问题解答

先看JLS 17.5里的原始示例代码:

class FinalFieldExample {
    final int x;
    int y;
    static FinalFieldExample f;

    public FinalFieldExample() {
        x = 3;
        y = 4;
    }

    static void writer() {
        f = new FinalFieldExample();
    }

    static void reader() {
        if (f != null) {
            int i = f.x; // guaranteed to see 3
            int j = f.y; // could see 0
        }
    }
}

当把构造器修改为以下形式后:

public FinalFieldExample() {
    y = 4;
    x = 3; 
}

我们来分析两个问题:

1. hb(y=4, f=new FinalFieldExample()) 是否成立?

成立。原因如下:

  • 同一线程内的程序顺序决定了hb(y=4, x=3)——先执行的操作happens-before后执行的操作。
  • 根据JLS的final字段冻结规则,hb(x=3, f=new FinalFieldExample())——final字段的赋值动作happens-before对象引用被发布(即赋值给f)的动作。
  • happens-before关系具备传递性:如果hb(A,B)且hb(B,C),则hb(A,C)。由此可推导出hb(y=4, f=new FinalFieldExample())成立。

2. reader()中的f.y是否能保证看到4?

不能保证。
虽然writer线程内部存在hb(y=4, f=new FinalFieldExample())的关系,但这仅约束writer线程内的操作顺序,无法保证reader线程能看到writer线程中y的赋值结果:

  • f是普通静态变量,writer线程对f的赋值和reader线程对f的读取之间没有happens-before关系。
  • 即便reader线程看到f != null,也可能因JVM对普通字段读写的重排序、缓存一致性问题,读取到y的初始值0。
  • 只有final字段的赋值会因冻结规则获得跨线程的可见性保证,普通字段没有这种特殊待遇。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:33:15