gpt4 book ai didi

java - 为什么Java构造函数不能同步?

转载 作者:行者123 更新时间:2023-12-01 04:30:08 25 4
gpt4 key购买 nike

根据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 是否有明确禁止构造函数上使用同步修饰符的原因?也许我上面的例子是有缺陷的,或者也许真的没有理由,这是一个任意的设计决定。无论哪种情况,我都很好奇并且很想知道答案。

最佳答案

如果您确实需要同步构造函数的其余部分与任何获取对尚未完全构造的对象的引用的线程,则可以使用同步块(synchronized block):

public class Test {
public Test() {
final Test me = this;
synchronized(this) {
new Thread() {
@Override
public void run() {
// ... Reference 'me,' the object being constructed
synchronized(me) {
// do something dangerous with 'me'.
}
}
}.start();
// do something dangerous with this
}
}
}

通常,像这样“给出”尚未构造的对象被认为是不好的风格,因此不需要同步构造函数。

<小时/>

在某些极端情况下,同步构造函数会很有用。这是一个更现实的例子,来自 Bozho 答案的讨论:

public abstract class SuperClass {

public SuperClass() {
new Thread("evil") { public void run() {
doSomethingDangerous();
}}).start();
try {
Thread.sleep(5000);
}
catch(InterruptedException ex) { /* ignore */ }
}

public abstract void doSomethingDangerous();

}

public class SubClass extends SuperClass {
int number;
public SubClass () {
super();
number = 2;
}

public synchronized void doSomethingDangerous() {
if(number == 2) {
System.out.println("everything OK");
}
else {
System.out.println("we have a problem.");
}
}

}

我们希望仅在子类对象的构造完成后才调用 doSomethingDangerous() 方法,例如我们只想要“一切正常”的输出。但在这种情况下,当你只能编辑你的子类时,你就没有机会实现这一点。如果构造函数可以同步的话,问题就解决了。

因此,我们了解到:如果您的类不是最终类,则永远不要在父类(super class)构造函数中执行像我在此处所做的那样的操作 - 并且不要从构造函数中调用您自己的类的任何非 final方法。

关于java - 为什么Java构造函数不能同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18051297/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com