Syncronization Question

Got a question I hope someone can answer for me (and tell me “bad idea” if that’s the answer)…


SomeObject myObject;

syncronized(myObject) {
     ...stuff...
      if(somecondition) myObject = new SomeObject();
      ...more stuff..
      myObject.methodthis(blah);
}

I’m pretty sure there are all sorts of race issues with creating a new version of the ‘locked’ object within a sync block like this. Can someone tell me for sure (or not) that this won’t stand up under a highly threaded environment…

Synchronization is done on objects, not on references to objects. If one thread synchronizes on the object that your myObject reference originally references and then makes myObject reference a new object, a second thread may be able to enter the synchronized block before the first thread has left the block since the second thread may synchronize on the new object that was assigned to the myObject reference by the first thread.

The risk of instruction reordering and caching issues inside the synchronized block probably also means that you can not be sure that the first thread has been able to execute anything inside the synchronized block before the second thread enters. In other words, you can probably not assume that your first line called ‘…stuff…’ has been executed, nor that the newly created SomeObject has been fully initialized in its constructor, even though it may seem (from a single-threaded perspective) like those things would have had to happen before the second thread could enter the block.

I guess there is no rule in Java that prevents VMs from crashing in this situation since a VM could theoreticly do the reference assignment before it has initialized the new object enough for it to be able to handle synchronization. The exact behaviour is quite OS and hardware specific though.

Thank you for the response - that goes along with what I was thinking also…

Won’t you get a null pointer if your trying to synchronize on a null pointer myObject? When it attemps to grab the monitor for myObject… well… there isn’t one yet!

But… even if myObject was initialized to some value… its bad bad idea to change what your pointer points to while inside of yoru synchronize block.

It’ll work… but its a bitch and a half to debug later on!

The JVM docs clearly states that every java type except 64 bit long and doubles, but including references are atomic. That is, if a thread assigns a value to a reference or a native type, another thread reading it will either get the old value (e.g. null) or the new value written by the first thread, but never a garbled value. That means that the jvm won’t ever be allowed to “crash”, only throw a NullPointerException or similar.

  • elias

As a purely hypothetical situation this would work (assuming myObject was intialized), but could create very strange situations.

The monitor will be on the original object, not the new object, therefore locks can occur on the new object just as if there was no lock. One would assume the reason for the lock was to prevent concurrent mutation of the object but that is not accomplished. Its conceivable that the object is locked by a second thread while a first thread is still in the synchronized block, which creates a race condition I’ve never really considered.

But beyond the theoretical question, obfuscating code, and the potential problems, there doesn’t seem to be any particullar efficency gained by taking this approach.