[concurrency-interest] Concurrency-interest Digest, Vol 52, Issue 1

Bharath Ravi Kumar reachbach at gmail.com
Sun May 3 06:12:33 EDT 2009


Hi Tim,

How does the local variable tmp help? Why not carry out a null checks on
(and subsequent assignment to) resource directly? Does the usage of tmp
reduce contention in any manner? Could you please explain?

Thanks,
Bharath



> From: Tim Peierls <tim at peierls.net>
> Subject: Re: [concurrency-interest] Reordering clarification in DCL
>        example
> To: Carol Saah <csaah at cox.net>
> Cc: concurrency-interest at cs.oswego.edu
> Message-ID:
>        <63b4e4050905020938u5c4ba444vec35d2ef003a5d11 at mail.gmail.com>
> Content-Type: text/plain; charset="iso-8859-1"
>
> 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-0001.html
> >
>
> ------------------------------
>
> Message: 3
> Date: Sat, 02 May 2009 13:10:58 -0400
> From: Carol Saah <csaah at cox.net>
> Subject: Re: [concurrency-interest] Reordering clarification in DCL
>        example
> To: Tim Peierls <tim at peierls.net>
> Cc: concurrency-interest at cs.oswego.edu
> Message-ID: <C621F6E2.1CA%csaah at cox.net <C621F6E2.1CA%25csaah at cox.net>>
> Content-Type: text/plain; charset="iso-8859-1"
>
> Tim,
>
> Thanks.  I?m not trying to find a way to fix DCL.  I am familiar with Item
> 71 in Effective Java.  And, section 16.2.4 of the Java Concurrency in
> Practice does not answer my questions.
>
> I?m trying to understand exactly what goes on under-the-covers when the
> compiler reorders code in incorrectly synchronized code.
>
> The example given in the old article does touch on what I am interesting in
> understanding.
>
> Carol
>
> On 5/2/09 12:38 PM, "Tim Peierls" <tim at peierls.net> wrote:
>
> > 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/2e031a2b/attachment-0001.html
> >
>
> ------------------------------
>
> Message: 4
> Date: Sat, 2 May 2009 10:12:32 -0700
> From: Joe Bowbeer <joe.bowbeer at gmail.com>
> Subject: Re: [concurrency-interest] Reordering clarification in DCL
>        example
> To: concurrency-interest <concurrency-interest at cs.oswego.edu>
> Message-ID:
>        <31f2a7bd0905021012w36e944beg3aaf2cf771482354 at mail.gmail.com>
> Content-Type: text/plain; charset="iso-8859-1"
>
> On Sat, May 2, 2009 at 9:38 AM, Tim Peierls wrote:
>
> > 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
> >
>
> A clarification of "fixed" that I think Tim would agree with:
>
> "Fixed" is used in the sense that if you have to have double-check locking,
> presumably for performance reasons, then this is one of the very few ways
> to
> code it correctly.
>
> On the other hand, this "fix" adds even more surface area to the code, and
> more modifiers for maintainers to contemplate ("volatile"), so as with all
> optimizations, it is best avoid going this route unless you really need it.
>
> Compiler: In JMM and DCL discussions, the "compiler" refers to javac plus
> JIT plus anything else that reorders or optimizes at the instruction level.
> In addition to the compiler(s), the processors and memory system (and
> anything that might be rigged to run Java apps), can reorder operations --
> but only to the extent allowed by the JMM.
>
> As you surmise, the danger here is that thread B will see a non-null
> reference to an incompletely constructed resource.
>
> Joe
>
> PS - The JMM FAQ could use another update on this topic:
>
> http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl<http://www.cs.umd.edu/%7Epugh/java/memoryModel/jsr-133-faq.html#dcl>
>
>
> On Sat, May 2, 2009 at 12:21 PM, Carol Saah 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
> >>
> >>
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <
> http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20090502/6695c706/attachment.html
> >
>
> ------------------------------
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
> End of Concurrency-interest Digest, Vol 52, Issue 1
> ***************************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20090503/7cf088e7/attachment-0001.html>


More information about the Concurrency-interest mailing list