[concurrency-interest] Double Checked Locking in OpenJDK

David Holmes davidcholmes at aapt.net.au
Wed Aug 15 21:42:42 EDT 2012

Chris Povirk writes:
> Thanks, that's definitely part of the picture.  My memory-model
> knowledge is very rusty, and it was never great, so here's one more
> round of questions.  First, I'll spell out some in-thread
> happens-before relationships:
> > local = new Vector();
> > synchronized (local) {}
> > shared = local;
> construction happens before synchronized block
> synchronized block happens before write
> (=> construction happens before write)

Nope. construction happens-before end of synchronized block. write also happens-before end of synchronized block. roach-motel rules allow everything to be moved into the sync block.
> > // other thread:
> > local = shared;
> > if (local != null) {
> >   synchronized (local) {}
> >   // safe to use local now?
> > }
> read happens before synchronized block
> synchronized block happens before use of local
> (=> read happens before use of local)

Again use of object could be moved inside the sync-block. But sync-block here can not be entered until after other thread releases the lock. So that establishes the happens-before ordering:

everything in writer thread happens-before release of lock
release of lock happens-before acquire of lock in second thread
acquire of lock happens-before use of object
=> everything in writer thread happens-before use of object

> The other thing that we want is for the write to happen before the
> read.  If it does, then we have construction HB write HB read HB use,
> and we're fine.  But the only cross-thread happens-before
> relationships I can imagine are conditional: *If* the writer's
> synchronized block happens before the reader's synchronized block,
> then yes, construction happens before use.  But if the *reader*'s
> synchronized block happens before the *writer*'s synchronized block,
> then all bets are off.  Or does that somehow guarantee that *none* of
> the writes from the writer thread are visible to the reader,
> guaranteeing that the reader can't see an incompletely initialized
> object by guaranteeing that it can't see the object at all?  Another
> (more likely?) possibility is that the writer's synchronized block is
> guaranteed to happen before the reader's, but I don't know enough
> rules to justify that.  Or is there a third option?

The above paragraph is confusing to me. The reader thread won't attempt to execute its sync block unless it sees the write to shared. The write to shared happens after the writer thread acquires the lock (and maybe after it releases it). So the reader will only attempt to acquire the lock once the writes have progressed to the point where shared was written, but it can't actually acquire the lock until all the writes are completed.

Hope that clarifies.


> Thanks again.

More information about the Concurrency-interest mailing list