当前位置: 首页 > 面试题库 >

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

岑畅
2023-03-14
问题内容

关于我先前关于不完整构造的对象的问题,我有第二个问题。正如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()保证实际上 调用
上面的私有构造函数(在这种情况下,原本打算使用的障碍将是安全的,并且一切都将是安全的),或者私有构造函数有可能作为一个 内联对象内联
到公共对象中优化以节省一个内存屏障(在这种情况下,直到公共构造函数的末尾才会有屏障)?

this()定义的规则正好在某处吗?如果没有,那么我认为我们必须假定允许内联链接的构造函数,并且可能某些JVM甚至javacs都在这样做。


问题答案:

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

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



 类似资料:
  • 我正在尝试实现一个链表。 列表有私有变量*头,*尾,计数。 我理解数据结构中的逻辑,但不可否认,我是C语言的新手,所以我觉得我可能没有正确地使用构造函数。 *head和*tail是列表节点指针。然后,列表节点具有指向上一个和下一个(双链接列表)的指针。 以下是我尝试过的: 我的程序可以编译,但当它试图使用此构造函数创建新列表时崩溃。有什么建议吗?

  • 问题内容: 有人可以说明一下可能有用的场景类型吗? 这是一种好的编程习惯吗? 问题答案: 这绝对是个好习惯,主要有两个原因: 避免代码重复 实施良好的封装

  • 问题内容: 这些来自github上的spring amqp示例,位于https://github.com/SpringSource/spring-amqp- samples.git 这些是 什么类型的Java构造函数?它们是吸气剂和吸气剂的捷径吗? 与此相反 问题答案: 这些构造函数被重载以使用调用另一个构造函数。第一个无参数构造函数使用空参数调用第二个。第二呼叫的第三构造(未示出),其必须采取,

  • 问题内容: 在Java中调用基类构造函数是强制性的吗?在C ++中,它是可选的,所以我问这个问题。 当我扩展时,我得到这个错误: 那么,调用基本构造函数的目的是什么?当我创建对象时,基类的构造函数将调用&然后涉及到派生权。 问题答案: 如果您自己不调用no- args构造函数,则该隐式调用;如果该构造函数不存在,则无效。要求调用超构造函数的原因是,超类通常在构造后会处于其预期的状态,其中可能包含无

  • 我正在学习C中的类,并且知道非静态成员函数具有隐式此参数。我的第一个问题是构造函数是否也像非静态成员函数一样具有隐式this参数。请注意,我不是在问我们是否可以在ctor中使用,因为我已经知道我们可以在ctor中使用。 接下来,我知道在类X的限定非静态成员函数中,这个函数的类型是const X*。对于非静态成员函数(无const限定),此的类型为X*。类似地,在ctor中,此的类型始终是X*。更深

  • 问题内容: 我有一些简单的Java代码,其结构与此类似: 我将有很多的子类,每个子类以自己的方式(模板方法模式)实现方法。 这很好用,但是我不喜欢子类中有多余的构造函数。输入更多,难以维护。如果要更改构造函数的方法签名,则必须更改所有子类。 当我从子类中删除构造函数时,出现此编译时错误: 我想做的事可能吗? 问题答案: 你会收到此错误,因为没有构造函数的类具有默认构造函数,该构造函数没有参数,并且