简体   繁体   English

基于该对象在同步块内分配对象(Java)

[英]Assigning an object within a synchronized block based on that object (Java)

I ran into some (production!) code that looks like the snippet below: 我遇到了一些(生产!)代码,看起来像下面的代码片段:

synchronized(some_object) {
    some_object = new some_object()
}

I would expect this to be subject to all sorts of horrible race conditions, and that a second thread Could possibly enter this block one the new object is created. 我希望这会受到各种可怕的竞争条件的影响,并且第二个线程可能会进入此块,创建一个新对象。 My Java chops aren't good enough to state definitively the expected behavior of above, so curious what you folks have to say before I refactor this. 我的Java排骨不够好,无法明确说明上面的预期行为,所以好奇你们重构之前你们要说的话。

This could actually be OK depending on what is going on. 根据发生的情况,这实际上可以是正常的。 You would need to understand the larger context. 您需要了解更大的背景。 The synchronization will be on the object that's pointed to by some_object at the beginning of the block. 同步将在块的开头由some_object指向的对象上。 There is not enough information from your description to see that it's a bug. 您的描述中没有足够的信息来确定它是一个错误。

The synchronization itself will work just fine. 同步本身也可以正常工作。

As Francis says, this may not be a problem. 弗朗西斯说,这可能不是问题。 Your snippet is equivalent to this: 您的代码段相当于:

SomeObject saved = some_object;
synchronized(saved) {
  some_object = new SomeObject()
}

The synchronization is on the object that was referenced when entering the synchronized block. 同步位于进入同步块时引用的对象上。 Pointing the reference to another object inside the synchronized block does not effect the synchronization at all. 将引用指向同步块内的另一个对象根本不会影响同步。 It is still synchronized over the "old" object. 它仍然在“旧”对象上同步。

This is pretty bad. 这很糟糕。 synchronized is best used on final class members. synchronized最适用于最终的成员。

The modern approach to creating an object in a thread safe manner is using AtomicReference compareAndSet in a loop as discussed in Goetz's Java Concurrency in Action (chap 15). 以线程安全方式创建对象的现代方法是在Goetz的Java Concurrency in Action(第15章)中讨论的循环中使用AtomicReference compareAndSet。 This does not block your threads and offers far greater performance than a synchronized block. 这不会阻塞您的线程,并且提供比同步块更高的性能。

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;
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM