Java规范 - 最终字段

时间:2015-10-22 08:13:12

标签: java

我正在阅读Java®语言规范Java SE 8版并且 17.5。最终的字段语义有一个例17.5-1。 Java内存模型中的最终字段https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#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
        } 
    } 
}

说明状态:

  

一个线程可能会执行方法编写器而另一个线程可能会执行   方法读者。   因为writer方法在对象的构造函数之后写入f   完成后,读者方法将保证正确看到   f.x的初始化值:它将读取值3.但是,f.y是   不是最终的;因此,读者方法无法保证看到   价值4。

我用两个线程编写了一些代码来重现这种情况但是当 reader 方法返回4以外的其他东西时我无法获得这种情况?总是将构造函数设置为4。

也许我无法理解。我将很感激地澄清这一点。

修改 谢谢大家,特别是 assylias Testing initialization safety of final fields完全向我解释。对我来说,这些句子是最重要的:

  

从Java 5.0开始,您将保证所有线程都能看到最终结果   由构造函数设置的状态。

     

实际上是确保构造函数在任何之前完成   随后的计划行动发生

1 个答案:

答案 0 :(得分:0)

通常,使用多线程应用程序很难获得所有可能性(特别是如果涉及缓存)。甚至不可能总是在所有JVM或操作系统或CPU上获得所有可能的结果。

假设以下内容: 线程1:使用writer方法创建f。 线程2:调用reader()。

为什么读者看到f非null和f.y与4不同?答案是,本地缓存可用于优化代码。比f创建,但y的值尚未更改。

编辑: "官方"回答,杰里米曼森可以找到here。 (感谢assylias'评论)