[concurrency-interest] Reordering clarification in DCL example

Carol Saah csaah at cox.net
Sat May 2 12:21:43 EDT 2009


Hello,

I understand from Brian Goetz that we should NOT use Double-Checked-Locking.

However, I am trying to understand exactly what can happen in the
incorrectly synchronized code that appears in the article, "Double-checked
locking: Clever, but broken."  I realize that
http://www.javaworld.com/jw-02-2001/jw-0209-double.html?page=4 is very old
and that some comments may be old; however, the reordering issue is not old.

The code in question is:

class SomeClass {
  private Resource resource = null;
  
  public Resource getResource() {
    if (resource == null) {
      synchronized (this) {
        if (resource == null)
          resource = new Resource();
      }
    }
    return resource;
  }
}

On page 4 of the article, "So what's broken about DCL?", I would like to get
a more precise description of the 1st scenario discussed in that section.
This is my understanding with questions.

The reordering discussed in the scenario happens in dynamic compilation and
would seem to happen once and apply to all threads for a class, correct?

And, does dynamic compilation happen just before JIT?

In the example, the compiler chooses to reorder the instructions of
getResource() to: allocate memory, assign reference to resource, call
constructor.  

But, in a thread, the as-if-sequential semantics hold, so do those
instructions happen AFTER the thread has done all of its work in the "local
memory."  

And, do the instructions apply to main memory only?

Here is the scenario in the example.

Thread A has invoked getResource() on a someClass object.

Thread A finds that resource is null and so Thread A invokes the constructor
for Resource and sets the resource.

Thread A still has not exited the synchronized block so no writes have been
made to main memory.

Thread A's state is in its "local memory" on the processor or cache in which
it is running.

But, before Thread B invokes, getResource(), these "reordered instructions"
happen for Thread A:  allocate memory, assign reference to resource

Now, Thread B invokes getResource().

Thread B finds the reference to resource that the "reordered" instructions
from Thread A put into main memory.

But, in the meantime, the processor executing the instructions for Thread A
still has not caused the constructor to execute in main memory so main
memory has a reference but nothing in it.

So, is this why Thread B is partially constructed?

Thanks.  

Carol Saah




More information about the Concurrency-interest mailing list