java - JVM 的隐式内存屏障在链接构造函数时如何表现?

标签 java constructor jvm compiler-optimization memory-barriers

引用我的earlier question on incompletely constructed objects ,我有第二个问题。正如 Jon Skeet 指出的那样,在构造函数的末尾有一个隐式内存屏障,它确保 final 字段对所有线程都是可见的。但是,如果构造函数调用另一个构造函数怎么办?他们每个人的末尾都有这样的内存障碍,还是仅在首先被调用的那个的末尾有这样的内存障碍?也就是说,当“错误”的解决方案是:

public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registerListener(
            new EventListener() {
                public void onEvent(Event e) {
                    doSomething(e);
                }
            });
    }
}

正确的应该是工厂方法版本:

public class SafeListener {
    private final EventListener listener;

    private SafeListener() {
        listener = new EventListener() {
            public void onEvent(Event e) {
                doSomething(e);
            }
        }
    }

    public static SafeListener newInstance(EventSource source) {
        SafeListener safe = new SafeListener();
        source.registerListener(safe.listener);
        return safe;
    }
}

下面的方法是否也有效?

public class MyListener {
    private final EventListener listener;

    private MyListener() {
        listener = new EventListener() {
            public void onEvent(Event e) {
                doSomething(e);
            }
        }
    }

    public MyListener(EventSource source) {
        this();
        source.register(listener);
    }
}

更新: 基本问题是 this() 保证实际调用 上面的私有(private)构造函数(在这种情况下会有预期的屏障,一切都是安全的),或者私有(private)构造函数是否有可能内联到公共(public)构造函数中作为一种优化来保存一个内存屏障(在这种情况下不会有障碍,直到公共(public)构造函数结束)?

this() 的规则是否在某处精确定义?如果不是,那么我认为我们必须假设允许内联链接的构造函数,并且可能某些 JVM 甚至 javac 正在这样做。

最佳答案

我认为它是安全的,因为 java 内存模型指出:

Let o be an object, and c be a constructor for o in which a final field f is written. A freeze action on final field f of o takes place when c exits, either normally or abruptly. Note that if one constructor invokes another constructor, and the invoked constructor sets a final field, the freeze for the final field takes place at the end of the invoked constructor.

关于java - JVM 的隐式内存屏障在链接构造函数时如何表现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2513841/

相关文章:

java - Mallet CRF 分类器出现 OutOfMemoryError

c++ - 默认构造函数 C++

java - java中如何临时标记对象

c - 基于(堆栈/注册)的虚拟机如何处理不同的数据类型

java - Mule 定制变压器

java - H2 是否为每个远程连接生成一个新线程?那么,有限制吗?

javascript - 为什么构造函数返回与自身同名的对象

java - System.out.println(16 >>> 3)?

java - 如何使用 JAXB 删除 XML 中的标签

c++ - 为什么传递给函数时会调用析构函数而不是构造函数?