[concurrency-interest] Double Checked Locking in OpenJDK

Zhong Yu zhong.j.yu at gmail.com
Tue Aug 14 15:58:44 EDT 2012


On Tue, Aug 14, 2012 at 2:52 PM, Vitaly Davidovich <vitalyd at gmail.com> wrote:
> Yes, presumably on some archs with very weak memory order it could cause
> some performance impact.  On TSO, it's just a compiler barrier preventing
> code motion that would publish the reference before constructor completes,
> but on those weak archs it could also mean a hardware fence.  Whether the
> tradeoff is worth it in general or not is debatable.  You can't have it both
> ways, I agree, but the jvm and JMM give you options and guidance on how to
> do the "right" thing.

If I'm writing a Java library, containing a Point(x,y) class, which is
immutable (in the narrower sense), should I use final fields or not?
What's the "right" thing to do?

If the answer is platform dependent, oh well.

Zhong Yu

>
> Sent from my phone
>
> On Aug 14, 2012 3:47 PM, "Zhong Yu" <zhong.j.yu at gmail.com> wrote:
>>
>> Are `final` fields a problem to compiler optimization?
>>
>> You can't have both ways.
>>
>> Either `final` field semantics is good and cheap, therefore it should
>> be extended to all fields.
>>
>> Or there is some downsides with 'final' field semantics, so we
>> shouldn't encourage people to apply `final` whenever they can. Lets
>> hear those downsides.
>>
>> Zhong Yu
>>
>> On Tue, Aug 14, 2012 at 2:42 PM, Vitaly Davidovich <vitalyd at gmail.com>
>> wrote:
>> > This is only an issue when publishing unsafely.  Allowing treating
>> > constructors as regular methods is a good thing as it gives the compiler
>> > a
>> > chance to optimize code, which everyone likes and benefits from.
>> >
>> > Sent from my phone
>> >
>> > On Aug 14, 2012 3:39 PM, "Zhong Yu" <zhong.j.yu at gmail.com> wrote:
>> >>
>> >> From a user's point of view, shouldn't constructors be special though?
>> >> An object shouldn't be considered in existence until its construction
>> >> is done; it is pathological that some outsider can observe a partially
>> >> constructed object. Life is simpler if we can eliminate that
>> >> possibility (unless `this` is leaked inside constructor)
>> >>
>> >> Zhong Yu
>> >>
>> >> On Tue, Aug 14, 2012 at 1:58 PM, Nathan Reynolds
>> >> <nathan.reynolds at oracle.com> wrote:
>> >> > 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


More information about the Concurrency-interest mailing list