[concurrency-interest] Double Checked Locking in OpenJDK

David Holmes davidcholmes at aapt.net.au
Wed Aug 15 19:51:12 EDT 2012


I stand corrected.

My previous characterization that the issue is that construction
happens-before use, was not accounting that the publication part is always
critical and so we must ensure that construction happens-before publication
which happens-before use.

Note that synchronized constructor also does not prevent assignment to the
reference being reordered with assignments in the constructor, but the
mutual exclusion aspect prevents that from being a problem.

Thanks,
David

  -----Original Message-----
  From: Vitaly Davidovich [mailto:vitalyd at gmail.com]
  Sent: Thursday, 16 August 2012 9:42 AM
  To: dholmes at ieee.org
  Cc: Ruslan Cheremin; concurrency-interest at cs.oswego.edu
  Subject: Re: [concurrency-interest] Double Checked Locking in OpenJDK



    If all your fields are final or volatile then you also have no issue
with
    publication.


  Volatile wouldn't help either as it won't prevent the possible reordering
of the assignment to the reference.  Final (or Unsafe.putXXXOrdered) is the
only solution (outside of synchronizing the constructor and the whole class
:)).

  On Aug 15, 2012 7:28 PM, "David Holmes" <davidcholmes at aapt.net.au> wrote:

    Ruslan Cheremin writes:
    >
    > > The reason to keep them distinct is because in general the
    > > mechanisms for safe publication are external to the class,
    > > while those for thread-safety are internal. It is only an
    > > edge case where use of synchronized in a constructor can
    > > achieve safe-publication.
    >
    > Well, actually I do not understand your point. If I use some kind of
    > synchronization to make methods of my object thread-safe -- can't I
    > also apply same thing to constructor? For me, it makes the thing only
    > clearer. Object can be thread-safe -- and it is totally thread safe.
    > Object can require external synchronization for correct multithreaded
    > use -- and it requires the sync for publishing and for usage also.

    You have to be able to establish the necessary happens-before
relationships
    between the end of construction, publication and use.

    If thread-safe means you've created a "monitor" where only one method
    invocation can proceed at a time and all methods are synchronized, then
    synchronized in the constructor will construction happens-before use,
and
    the publication mechanism is not relevant.

    If all your fields are final or volatile then you also have no issue
with
    publication.

    Otherwise you have a bit more work to do. Relying on safe-publication to
    introduce the happens-before ordering allows you to use simpler, more
    natural, and likely more performant code in your thread-safe class.

    David
    -----


    > From my point of view, the distinction you talking about is more
    > historically reasoned. "Sync method if you want it to be thread-safe"
    > is commonly learned mantra, but "take care of initialization also" is
    > not so common. More information about it, more education, more
    > different code samples with outlined "here is the dragons" will change
    > the situation, I sure, it just have to be highlighted more often.
    >
    >
    > > People have to recognize that sharing an object requires shared
mutable
    > > state, and the number one tenet of concurrent programming is
    > that access to
    > > shared mutable state has to be synchronized (in a general sense not
    > > specifically use of 'synchronized' keyword).
    > >
    > > Making every object safely publishable could be done, but for
    > 99% of objects
    > > it would be a waste of effort. Programs without data races
    > don't have issues
    > > with unsafe publication.
    > >
    > > David
    > >
    > > -----Original Message-----
    > > From: concurrency-interest-bounces at cs.oswego.edu
    > > [mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of
Nathan
    > > Reynolds
    > > Sent: Wednesday, 15 August 2012 4:59 AM
    > > To: concurrency-interest at cs.oswego.edu
    > > Subject: Re: [concurrency-interest] Double Checked Locking in
OpenJDK
    > >
    > > We seem to be splitting two notions (i.e thread-safe and safe
    > publication)
    > > when they should be combined in a sense.  Typically, when we
    > say thread-safe
    > > we talk about the operations performed on the object after it was
    > > constructed (and its contents are globally visible).  However,
    > we need to
    > > consider that executing the constructor is modifying the state of
the
    > > object.  It requires the same mechanisms that the rest of the
    > class uses to
    > > ensure thread-safety.  Even though, there is only 1 thread executing
the
    > > constructor, a proper releasing of a lock or some other
happens-before
    > > construct is required to ensure that the memory updates by the
    > thread are
    > > made globally visible before the object is accessed by another
    > thread.  This
    > > is what we are calling safe publication.  So, safe publication
    > is a subset
    > > of thread-safety except it is limited to what happens after the
    > constructor
    > > is called and before the object is used by multiple threads.
    > >
    > > A beautifully-written class can be thread-safe with respect to
    > calling its
    > > member methods but not thread-safe with respect to calling its
    > constructor.
    > > It is this latter case that many stumble upon because they think
that
    > > constructors are inherently thread-safe because they are executed
    > > single-threadedly.  What they fail to realize is that the execution
of a
    > > constructor can overlap with the execution of other code from
    > the view point
    > > of what is happening in memory.  This same problem applies to
    > more rare case
    > > of regular methods which can be proven to execute in a single thread
but
    > > don't use synchronization before multiple threads start
    > accessing the shared
    > > data.
    > >
    > > Nathan Reynolds | Consulting Member of Technical Staff |
602.333.9091
    > > Oracle PSR Engineering | Server Technology
    > > On 8/13/2012 4:08 PM, David Holmes wrote:
    > >
    > > Ruslan Cheremin writes:
    > >
    > > For me it is confusing: java has only one way to have really
immutable
    > > object, and this way also gives you a total thread safety even for
    > > data race based publication. But then docs refer object as
"immutable
    > > and thread-safe" -- we still can't assume it to be really
thread-safe?
    > >
    > > It is better/simpler to isolate the notion of thread-safety and safe
    > > publication. Thread-safety comes into play after you have
    > safely shared an
    > > object. The means by which you safely share an object is
    > orthogonal to how
    > > the object itself is made thread-safe.
    > >
    > > The means by which an object is shared has to involve shared
    > mutable state,
    > > and use of shared mutable state always needs some form of
    > synchronization
    > > (either implicit eg due to static initialization; or explicit by
using
    > > volatile or synchronized getter/setter methods).
    > >
    > > David
    > > -----
    > >
    > > It's a pity, especially because true immutability gives us some
    > > chances of performance optimization. As in this case -- we do not
    > > really need .path to be volatile here, if we would assume Path to be
    > > truly immutable. volatility here required only for ensuring safe
    > > publishing.
    > >
    > > 2012/8/13 David Holmes <davidcholmes at aapt.net.au>:
    > >
    > > Ruslan Cheremin writes:>
    > >
    > > But is there a way to define "safe for data race publishing"? I as
    > > far, as I remember, "immutable and thread-safe" is standard mantra
in
    > > JDK javadocs for totally safe objects. j.l.String has same mantra --
    > > and it is safe for any way of publishing. Does you mean, I should
    > > explicitly add "safe even for publishing via data race" in docs? But
I
    > > can't remember any such phrase in JDK docs.
    > >
    > > I don't recall anything in the JDK docs that mention being
    > >
    > > "totally safe"
    > >
    > > regardless of publication mechanism. Some classes, eg String, have
been
    > > defined such that they do have that property (for security reasons).
In
    > > general neither "thread-safe" nor "immutable" imply
    > > safe-for-unsynchronized-publication.
    > >
    > > Java Concurrency In Practice (jcip.net) does define additional
potential
    > > annotations, where @Immutable would indeed capture the requirement
of
    > > safe-for-unsynchronized-publication.
    > >
    > > David
    > > -----
    > >
    > > 2012/8/13 David Holmes <davidcholmes at aapt.net.au>:
    > >
    > > Ruslan Cheremin writes:
    > >
    > > Well, Path javadoc explicitly says "immutable and safe for
    > > multithreaded use". Although it is not strictly defined in java what
    > > exactly means "safe for multithreaded use" -- does it mean safe for
    > > publishing via data race, among others? -- I suppose, it
    > >
    > > should be. Am
    > >
    > > I wrong here?
    > >
    > > "safe for multi-threaded use" does not generally imply that it
    > >
    > > is safe to
    > >
    > > publish instances without synchronization of some form.
    > >
    > > David
    > > -----
    > >
    > > From other side, File.toPath javadoc explicitly says what "returned
    > > instance must be the same for every invocation", so sync block is
    > > required here for mutual exclusion on initialization phase. Without
    > > this requirement it is also safe to live without sync block, afaik.
    > >
    > > 2012/8/13 David Holmes <davidcholmes at aapt.net.au>:
    > >
    > > Ruslan Cheremin writes:
    > >
    > > First of all, Path is immutable, so DCL is safe here even without
    > > volatile. Volatile here is not required from my point of view.
    > >
    > > Without the volatile the Path implementation (Path is an
    > >
    > > interface) must be
    > >
    > > such that an instance of Path can be safely published without
    > >
    > > any additional
    > >
    > > forms of synchronization. Immutability does not in itself
    > >
    > > ensure that. You
    > >
    > > would have to examine the actual implementation class.
    > >
    > > David Holmes
    > > ------------
    > >
    > > 2012/8/12 Dmitry Vyazelenko <vyazelenko at yahoo.com>:
    > >
    > > Hi Richard,
    > >
    > > The variable "filePath" is volatile, so the double-checked
    > >
    > > locking is correct in this case. It would have been a bug
    > >
    > > prior to Java 5.
    > >
    > > Best regards,
    > >
    > > Dmitry Vyazelenko
    > >
    > > On Aug 12, 2012, at 21:35 , Richard Warburton
    > >
    > > <richard.warburton at gmail.com> wrote:
    > >
    > > Hello,
    > >
    > > The current implementation of java.io.File::toPath [0]
    > >
    > > appears to be
    > >
    > > using the double checked locking pattern:
    > >
    > >     public Path toPath() {
    > >         Path result = filePath;
    > >         if (result == null) {
    > >             synchronized (this) {
    > >                 result = filePath;
    > >                 if (result == null) {
    > >                     result =
    > >
    > > FileSystems.getDefault().getPath(path);
    > >
    > >                     filePath = result;
    > >                 }
    > >             }
    > >         }
    > >         return result;
    > >     }
    > >
    > > I was going to report the bug, but I'm a little
    > >
    > > uncertain of the
    > >
    > > interaction between the local variable 'result' and DCL
    > >
    > > since I've
    > >
    > > previously only seen the checking condition on the
    > >
    > > shared field
    > >
    > > itself.  Can someone here either confirm that its a bug or
    > >
    > > explain how
    > >
    > > the 'result' variable is fixing things?
    > >
    > > regards,
    > >
    > >  Richard
    > >
    > > [0] See the end of
    > >
    > > hg.openjdk.java.net/jdk8/jdk8/jdk/file/da8649489aff/src/share/clas
    > >
    > > ses/java/io/File.java
    > >
    > > _______________________________________________
    > > Concurrency-interest mailing list
    > > Concurrency-interest at cs.oswego.edu
    > > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
    > >
    > > _______________________________________________
    > > Concurrency-interest mailing list
    > > Concurrency-interest at cs.oswego.edu
    > > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
    > >
    > > _______________________________________________
    > > Concurrency-interest mailing list
    > > Concurrency-interest at cs.oswego.edu
    > > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
    > >
    > > _______________________________________________
    > > Concurrency-interest mailing list
    > > Concurrency-interest at cs.oswego.edu
    > > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
    > >
    > >
    > >
    > > _______________________________________________
    > > Concurrency-interest mailing list
    > > Concurrency-interest at cs.oswego.edu
    > > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
    > >
    >

    _______________________________________________
    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/20120816/87d4a7de/attachment-0001.html>


More information about the Concurrency-interest mailing list