[concurrency-interest] Double Checked Locking in OpenJDK

David Holmes davidcholmes at aapt.net.au
Wed Aug 15 03:32:57 EDT 2012


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.

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.

  -----Original Message-----
  From: concurrency-interest-bounces at cs.oswego.edu
[mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Nathan
  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

  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).


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

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

Java Concurrency In Practice (jcip.net) does define additional potential
annotations, where @Immutable would indeed capture the requirement of


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.


>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:

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 =
                    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?



[0] See the end of

Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu

Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu

Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20120815/71186c95/attachment.html>

More information about the Concurrency-interest mailing list