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

Joo*_*kka 14 java constructor jvm compiler-optimization memory-barriers

参考我之前关于不完整构造对象的问题,我有第二个问题.正如Jon Skeet指出的那样,在构造函数的末尾有一个隐式的内存障碍,可以确保final所有线程都可以看到这些字段.但是如果构造函数调用另一个构造函数呢?在每个人的最后是否有这样的记忆障碍,或者只是在第一个被召唤的人的最后?也就是说,当"错误"解决方案是:

public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registerListener(
            new EventListener() {
                public void onEvent(Event e) {
                    doSomething(e);
                }
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

正确的一个是工厂方法版本:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下工作是否也会起作用?

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

this()准确定义的规则是什么?如果没有,那么我认为我们必须假设允许内联链接构造函数,并且可能是一些JVM甚至可能javac正在执行它.

小智 6

我认为这是安全的,因为java内存模型声明:

o为对象,co的构造函数,其中写入最终字段f.当c退出时,正常或突然发生对o的最终场f的冻结动作.请注意,如果一个构造函数调用另一个构造函数,并且调用的构造函数设置了final字段,则最终字段的冻结将在调用的构造函数的末尾进行.