Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java:为什么不允许它转义构造函数?_Java_Concurrency - Fatal编程技术网

java:为什么不允许它转义构造函数?

java:为什么不允许它转义构造函数?,java,concurrency,Java,Concurrency,在JCIP的第3.2.1节“安全构造函数实践”中,有一个警告,警告不要将此泄漏到构造函数的另一个线程,“即使发布是构造函数中的最后一条语句。”最后一部分对我来说似乎太强了,而且没有提供任何理由。施工后发生了什么事,我必须小心避免?有例外吗?我很感兴趣,因为我最近提交了一些代码,我在其中做了这件事,我想决定是否有理由回去进行重构。你不应该在任何时候从构造函数中泄露这个,“甚至在最后一条语句中[…]由于这个不是完全构建的,所以可能会发生一些非常奇怪的事情。请看一个非常类似的问题 您不应将此传递出构造

在JCIP的第3.2.1节“安全构造函数实践”中,有一个警告,警告不要将
泄漏到构造函数的另一个线程,“即使发布是构造函数中的最后一条语句。”最后一部分对我来说似乎太强了,而且没有提供任何理由。施工后发生了什么事,我必须小心避免?有例外吗?我很感兴趣,因为我最近提交了一些代码,我在其中做了这件事,我想决定是否有理由回去进行重构。

你不应该在任何时候从构造函数中泄露
这个
,“甚至在最后一条语句中[…]由于
这个
不是完全构建的,所以可能会发生一些非常奇怪的事情。请看一个非常类似的问题

您不应将
传递出构造函数(称为“泄漏
”)

即使是构造函数的最后一行,也不应该这样做的一个原因是,只要对当前线程的影响不受影响,JVM就可以对语句重新排序。如果
将此
传递给另一个线程中运行的进程,则重新排序可能会导致奇怪而微妙的错误


另一个原因是子类可能提供自己的初始化,因此在类的构造函数的最后一行构造可能不完整。

就Java内存模型而言,构造函数出口在最终字段语义中起作用,因此,语句是在构造函数退出之前还是之后是有区别的

This works                         This doesn't work
-------------------------------------------------------------

static Foo shared;                 static Foo shared;

class Foo                          class Foo
{                                  {   
    final int i;                       final int i; 
    Foo()                              Foo() 
    {                                  {
        i = 1;                             i = 1;
                                           shared = this;  
    }                                  }
}                                  }

shared = new Foo();                new Foo();
(注意:
shared
不是易变的;发布是通过数据竞争进行的。)

这两个示例之间的唯一区别是在构造函数退出之前或之后分配
shared
。在第二个示例中,
i=1
允许在赋值后重新排序

但是,如果发布是一个同步的操作,例如通过一个易失性变量,那么就可以了;其他线程将观察一个完全初始化的对象;这些字段甚至不必
final

通过数据竞赛发布(或通过数据竞赛做任何事情)是一项非常棘手的业务,需要非常仔细的推理。如果您避免数据竞争,事情就会简单得多如果您的代码不包含数据竞争,那么在构造函数退出之前立即泄漏
与在构造函数退出之后立即发布它之间没有区别。