链接构造函数时JVM的隐式内存屏障如何工作? [英] How do JVM's implicit memory barriers behave when chaining constructors?

查看:236
本文介绍了链接构造函数时JVM的隐式内存屏障如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考我的有关未完全构建的对象的问题,我有一个第二个问题。正如Jon Skeet指出的,在构造函数的结尾有一个隐式的内存障碍,它确保 final 字段对所有线程可见。但是如果一个构造函数调用另一个构造函数呢?在每个人的最后是有这样一个记忆障碍,还是只有在被调用的那个人的结尾?也就是说,当错误的解决方案是:

Referring to my earlier question on incompletely constructed objects, I have a second question. As Jon Skeet pointed out, there's an implicit memory barrier in the end of a constructor that makes sure that final fields are visible to all threads. But what if a constructor calls another constructor; is there such a memory barrier in the end of each of them, or only in the end of the one that got called in the first place? That is, when the "wrong" solution is:

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

正确的是工厂方法版本:

And the correct one would be a factory method version:

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;
    }
}

p>

Would the following work too, or not?

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()保证实际上调用上面的私有构造函数(在这种情况下,会有障碍,安全),或者私有构造函数可以被内联到公共构造函数中作为优化以节省一个内存屏障(在这种情况下,直到公众结束才会有屏障)构造函数)?

Update: The essential question is that is this() guaranteed to actually call the private constructor above (in which case there would be the barrier where intended and everything would be safe), or is it possible that the private constructor gets inlined into the public one as an optimization to save one memory barrier (in which case there wouldn't be a barrier until in the end of the public constructor)?

this()的规则是否在某处定义?如果没有,那么我想我们必须假设允许内联链接构造函数,并且可能一些JVM或者甚至 javac 都在做。

Are the rules of this() defined precisely somewhere? If not, then I think we must assume that inlining chained constructors is allowed, and probably some JVMs or maybe even javacs are doing it.

推荐答案

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

I think it is safe as java memory model states that:


o 是一个对象, c o 的构造函数,其中最后
字段。当 c 正常或突然退出时,会发生
o 最后一个字段上的冻结动作。注意,如果一个
构造函数调用另一个构造函数,并且被调用的构造函数
设置了一个final字段,则最终字段的冻结发生在被调用构造函数的
end。

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.

这篇关于链接构造函数时JVM的隐式内存屏障如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆