我遇到了一些(生产!)代码,如下所示:
synchronized(some_object) {
some_object = new some_object()
}
我希望这会受到各种可怕的竞争条件的影响,并且第二个线程可能会在创建新对象时进入这个块。我的 Java 印章不足以明确说明上述预期的行为,所以在我重构之前你们必须说些什么。
我遇到了一些(生产!)代码,如下所示:
synchronized(some_object) {
some_object = new some_object()
}
我希望这会受到各种可怕的竞争条件的影响,并且第二个线程可能会在创建新对象时进入这个块。我的 Java 印章不足以明确说明上述预期的行为,所以在我重构之前你们必须说些什么。
这实际上可能没问题,具体取决于发生了什么。您需要了解更大的背景。同步将在some_object
块开头指向的对象上进行。您的描述中没有足够的信息表明这是一个错误。
同步本身就可以正常工作。
正如弗朗西斯所说,这可能不是问题。您的代码段相当于:
SomeObject saved = some_object;
synchronized(saved) {
some_object = new SomeObject()
}
同步在进入同步块时引用的对象上。将引用指向同步块内的另一个对象根本不会影响同步。它仍然在“旧”对象上同步。
这很糟糕。同步最好用于最终类成员。
以线程安全方式创建对象的现代方法是在循环中使用 AtomicReference compareAndSet,如 Goetz 的 Java Concurrency in Action(第 15 章)中所述。这不会阻塞您的线程,并且提供比同步块更高的性能。
private final AtomicReference<SomeObject> someObject = new AtomicReference<>();
void buildIt() {
SomeObject obj = new SomeObject();
SomeObject current = someObject.get(); //probably null, but doesn't matter
while (true) {
if (someObject.compareAndSet(current, obj))
break;
}
}