RE: JavaMemoryModel: Unsynchronized read as an optimization

From: David Holmes (dholmes@dstc.edu.au)
Date: Sat Dec 16 2000 - 06:59:43 EST


I'll play devil's advocate here and try and force a more complete
denunciation out
of Bill. :) I think the code is correct given the current specification but
will not
be in the proposed revised spec.

> class Foo {
> private Helper helper = null;
> private boolean helperExists;
> public Helper getHelper() {
> if (!helperExists)
> synchronized(this) {
> if (helper == null)
> helper = new Helper();
> else
> helperExists = GlobalSettings.ALLOW_UNSYNCHRONIZED_READ;
> }
> return helper;
> }

The basic problem with double-check in the singleton example is that it only
makes the
first write perform sync, not the readers, when for correctness each reader
needs to sync at least once. The code above forces at least the first two
threads to do sync and uses the ordering constraints that the actions of
those threads imply, to allow future threads to go without sync.

Assuming ALLOW_UNSYNCHRONIZED_READ is true, we have the following initial
situation:

Thread 1 reads helperExists for the first time, it must read it from main
memory according to the spec because it is unseen, and so will see false.
Under sync it will then initialise helper.

Thread 2, by the same reasoning will also see helperExists as false, will
grab the lock, see that helper is set and so set helperExists to true.

Thread 3, may see helperExists to be either true or false. If it's false
then it will perform the sync and all is well. If it sees true then it will
read helper - and as this is the first time it has accessed helper it must
read it from main memory. Now as the actions on main memory are ordered by
the locking actions of threads 1 and 2 it follows that helper had to be set
in main memory before helperExists and so, with a coherent view of main
memory (as per the current spec), helper can not be null.

Under the revised/proposed specification there will be no guarantee that
thread 3 sees helper or any of its fields correctly unless it acquires the
same lock as used by threads 1 and 2 (or else the final/volatile idioms are
used). The relaxed requirements of the new spec do not require that thread 3
see main memory the same way as threads 1 and 2 - so even if helperExists is
seen as true, helper (or its fields) may not be initialised.

David Holmes
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:29 EDT