首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java内存模型及最终字段

Java内存模型及最终字段
EN

Stack Overflow用户
提问于 2013-11-13 23:34:28
回答 3查看 4.8K关注 0票数 1

最近,当我提到JMM提供与"final“相关的保证时,我感到很困惑。以下是JMM的摘录和示例

图4给出了一个示例,演示了finalfi屏蔽与普通fi屏蔽的比较。类FinalFieldExample具有一个final intfield x和一个非final intfield y,一个线程可以执行方法编写器(),另一个线程可以执行方法读取器()。因为编写器()在对象的构造函数finishes之后写入f,所以阅读器()将保证看到F.X的正确初始化值:它将读取值3。然而,f.y不是final;因此,reader()方法不能保证看到它的值4。

代码语言:javascript
复制
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
      }
    }
}

我的困惑是,对象'Obj‘有最终字段和非最终字段是完全初始化的,并且被线程'T’引用,T只会看到最终字段的正确值?建设后不会发生变异的非最终字段怎么办?我知道,如果它们在构造后发生变异,线程'T‘可能看不到新的值(除非字段是易失性的)。但是,如果这个领域是非最终的,非易变的,并且在建造后不发生变异,我会怎样呢?

JVM如何实现与'final‘相关联的保证?例如,对于易挥发的,有记忆障碍。

EN

回答 3

Stack Overflow用户

发布于 2013-11-13 23:50:32

这一问题在本答复中得到了解决:

这是对象的安全发布吗?

引用如下:

问题的核心是优化和重新排序指令。如果有两个线程正在使用未同步的构造对象,则可能会发生以下情况:为了提高效率,编译器决定重新排序指令,并为对象分配内存空间,并在item字段完成构造函数和字段初始化之前将其引用存储在其中。或者,它可以重新排序内存同步,以便其他线程能够这样理解它。

如果将某个字段标记为最终字段,则强制编译器在构造函数完成之前完成该字段的初始化。非最终字段没有这样的保证。

这是Java语言定义(17.4)的一部分。关于final字段的详细信息也在JLS (17.5)中。

更具体地说,writer()方法构造一个FinalFieldExample实例,并将其存储在static字段中,供其他线程使用。由于指令重新排序,y字段可能尚未初始化。如果同一个线程调用reader(),它将将y视为4,但其他线程可能会将其视为0,因为f可能是在初始化和发布y之前设置和使用的。

要使代码正确,您必须使f也成为volatile

票数 6
EN

Stack Overflow用户

发布于 2013-11-14 02:27:32

JVM如何实现与'final‘相关联的保证?例如,对于易挥发的,有记忆障碍。

为了遵守final字段的语义,不能进行一些重新排序,可能需要一些内存屏障(在某些处理器上)。请参阅http://g.oswego.edu/dl/jmm/cookbook.html

这意味着final不是免费午餐。在我们在任何地方使用final之前都要考虑到这一点。(仅仅因为它在约书亚的书中并不意味着它是正确的)

票数 3
EN

Stack Overflow用户

发布于 2013-11-13 23:47:25

我的困惑是,对象'Obj‘有最终字段和非最终字段是完全初始化的,并且被线程'T’引用,T只会看到最终字段的正确值?

保证所有线程都能看到final字段的正确值。这与非最终字段无关。

建设后不会发生变异的非最终字段怎么办?

final修饰符仅适用于特定字段。您可能会对其他非最终字段感到“幸运”,但保证只适用于标记为final的字段。

非最终字段是在构造函数中设置的,而不是稍后修改的,这与此无关。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19966662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档