我遇到了一些(生产!)代码,看起来像下面的代码段:
synchronized(some_object) {
some_object = new some_object()
}
我希望这会受到各种可怕的竞争条件的影响,并且第二个线程可能会进入此块,创建一个新对象。我的Java排骨不够好,无法明确说明上面的预期行为,所以好奇你们重构之前你们要说的话。
答案 0 :(得分:4)
这实际上可以是正常的,具体取决于发生了什么。您需要了解更大的背景。同步将在块的开头由some_object
指向的对象上。您的描述中没有足够的信息来确定这是一个错误。
同步本身就可以正常工作。
答案 1 :(得分:2)
弗朗西斯说,这可能不是问题。您的代码段相当于:
SomeObject saved = some_object;
synchronized(saved) {
some_object = new SomeObject()
}
答案 2 :(得分:1)
同步位于进入同步块时引用的对象上。将引用指向同步块内的另一个对象根本不会影响同步。它仍然在“旧”对象上同步。
答案 3 :(得分:1)
这很糟糕。 synchronized最适用于最终的成员。
以线程安全方式创建对象的现代方法是在循环中使用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;
}
}