【发布时间】:2011-06-20 07:01:05
【问题描述】:
根据the Java Language Specification,构造函数不能标记为同步,因为在创建它的线程完成之前,其他线程无法看到正在创建的对象。这似乎有点奇怪,因为我确实可以让另一个线程在构建对象时查看它:
public class Test {
public Test() {
final Test me = this;
new Thread() {
@Override
public void run() {
// ... Reference 'me,' the object being constructed
}
}.start();
}
}
我知道这是一个非常人为的例子,但理论上似乎有人可以提出一个更现实的情况,将构造函数标记为同步是合法的,以防止像这样的线程竞争。
我的问题是:Java 是否有理由明确禁止构造函数上的同步修饰符?也许我上面的例子有缺陷,或者真的没有理由,这是一个任意的设计决定。无论哪种情况,我都很好奇,很想知道答案。
【问题讨论】:
-
顺便说一句,强烈建议在构造函数完成之前不要让“this”引用转义。
-
@Mike Q- 我以前听说过这个,但不完全明白为什么。有什么特别的原因吗?如果您在完成初始化对象之前给出对 this 的引用,我可能会看到坏事发生,但如果这是您在构造函数中做的最后一件事呢?
-
这确实是另一个问题的主题,但即使它是你在构造函数中做的最后一件事,如果对象被子类化,那么子类还没有完成构造。如果这个类是最终的,并且您没有链接构造函数(调用 this(...))并且在链调用之后执行其他操作并且这是您做的最后一件事,那很好。当然,这些决定中的任何一个都可能改变(您可以稍后添加第二个构造函数)。
-
如果你引用 JLS 的实际说法会更清楚:“没有实际需要同步构造函数,因为它会锁定正在构建的对象,这通常在对象的所有构造函数完成其工作之前,其他线程不会使用。"
标签: java constructor language-design synchronized