[concurrency-interest] Reordering clarification in DCL example

Tim Peierls tim at peierls.net
Sat May 2 12:38:25 EDT 2009


See more recent discussions in Java Concurrency in Practice, Section 16.2.4
and Effective Java, 2nd edition, Item 71.
The fixed version of the code is:

class SomeClass {
  private volatile Resource resource;

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

--tim

On Sat, May 2, 2009 at 12:21 PM, Carol Saah <csaah at cox.net> wrote:

> 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
>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20090502/8937e0cd/attachment.html>


More information about the Concurrency-interest mailing list