Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 864
Peter Friend Avatar asked May 24 '12 23:05

Peter Friend


4 Answers

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. There is not enough information from your description to see that it's a bug.

The synchronization itself will work just fine.

like image 161
Francis Upton IV Avatar answered Nov 09 '22 18:11

Francis Upton IV


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()
}
like image 2
Stefan Haustein Avatar answered Nov 09 '22 19:11

Stefan Haustein


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.

like image 1
Fabian Barney Avatar answered Nov 09 '22 18:11

Fabian Barney


This is pretty bad. synchronized is best used on final class members.

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). 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;
   }
}
like image 1
marathon Avatar answered Nov 09 '22 18:11

marathon