RE: JavaMemoryModel: Immutablity and Final Fields

From: Jeremy Manson (jmanson@cs.umd.edu)
Date: Mon Feb 26 2001 - 20:27:27 EST


>
> Copying into a thread-local variable certainly avoids the overhead of using
> either a volatile reference or a synchronized accessor to the reference, but
> requires a different approach to the way things are typically done at
> present. If access to the object is within a simple scope then it is
> feasible to use a local stack-based variable to hold the thread-local copy.
> In general however these shared variables tend to be accessed from various
> methods in various classes - take the Singleton pattern as an example. In
> that case the only way to get a thread-local copy is to use a real
> ThreadLocal accessed via the Singleton class.
>
> public class Singleton {
> private static theInstance = null;
>
> private ThreadLocal localInstance = new ThreadLocal();
>
> public static Singleton getInstance() {
> Singleton local = (Singleton) localInstance.get();
> if (local == null) {
> synchronized (Singleton.class) {
> if (theInstance == null)
> theInstance = new Singleton();
> }
> localInstance.set(theInstance);
> return theInstance;
> }
> return local;
> }
> }
>
> I wonder how the overhead of ThreadLocal compares to either a synchronized
> accessor or a volatile reference. ;-)

It is implemented as a synchronizedMap in Sun's JDK, IIRC.

>
> Many of these situations boil down to what you describe: each thread needs
> to get synchronized access to the reference to the shared object only the
> first time they access it. Finding a way to pay for that synchronization
> only once is one of the goals.

Seems to me that you could associate the barrier with an instance of the
thread object. It isn't nice and object-oriented (and I can hear the
cries of pain now), but it would work. Consider the following.

class myThread extends Thread {

  public Singleton initSynch;

}

 public class Singleton {
     private static Singleton theInstance = null;

     public static Singleton getInstance() {
         myThread thisThread = (myThread) Thread.currentThread();
         Singleton local = thisThread.initSynch;
         if (local == null) {
             synchronized (Singleton.class) {
                 if (theInstance == null)
                     theInstance = new Singleton();
              }
             thisThread.initSynch = theInstance;
             return theInstance;
         }
         return local;
     }
 }

I would certainly discourage this as bad style, but it gets around the
synchronization issue. A slightly better style, which confuses the
example, and makes it slower, would have a hashTable of references (or
something) in myThread. The abstraction there would be something like
"this table is a list of all initialized read-only objects the thread
can use". That adds overhead, but not the same overhead as a
synchronizedMap (probably).

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



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