JavaMemoryModel: Thread Synchronization at Creation and Termination

From: Victor Luchangco (victor_l@raven.lcs.mit.edu)
Date: Wed Feb 07 2001 - 10:05:31 EST


Hi,

I have a question about the synchronization of constructors, and the
start and join methods of threads. I am just joining this list now,
and so I haven't had a chance to read up on all the stuff that has
previously gone over. I'm sending this question to this mailing list
at the suggestion of Dave Detlefs, who kindly pointed me to all this
discussion on memory consistency in Java. (My main research is on
memory consistency in shared memory multiprocessors, but many of the
issues are the same... except for compilation, which is a big
"except".)

Anyway, my question is this:

After reading the JLS spec, and various other things (Bill Pugh's
"Fixing the Java memory model" paper, and other stuff on the website),
I still couldn't find any definitive word about the memory consistency
guarantees for thread creation, "starting" and synchronization (via
join, not the synchronized statements). Here's a sample program that
illustrates the specific question I have:

        class UnsyncRegister
        {
          int val = 0;
          
          public int read()
          {
            return val;
          }
          
          public void write(int newval)
          {
            val = newval;
          }
        }
        
        class CopyThread extends Thread
        {
          UnsyncRegister readreg, writereg;
          
          public CopyThread(UnsyncRegister rr, UnsyncRegister wr)
          {
            readreg = rr;
            writereg = wr;
          }
          
          public void run()
          { /* Copies readreg into writereg */
            writereg.write(readreg.read());
          }
        }
        
        public class Program
        {
           public static void main(String args[])
           {
             int val;
             UnsyncRegister r1 = new UnsyncRegister();
             UnsyncRegister r2 = new UnsyncRegister();
             
             /* copies r1 into r2 */
             CopyThread copier = new CopyThread(r1, r2);
             
             r2.write(5);
             r1.write(3);
             
             copier.start(); /* should copy r1 into r2 */
             try{
               copier.join(); /* wait for copy to complete */
             } catch(InterruptedException e){
               System.err.println("Caught interrupted exception");
             }

             val = r2.read(); /* get value in r2 */
             /* can val be 5? (can it be 0?) */

             System.out.println("Value = " + val);
           }
        }

I'm pretty sure that from the JLS spec alone, you can get either
val = 5 or val = 0 (or whatever val inside an UnsyncRegister initializes
if it become visible before the initial val = 0 gets done). This seems
like an obviously crazy possibility to me. In particular, this program
is really almost sequential. I don't really program in Java, but it
seems like asking for trouble to expect programmers to anticipate these
results. (Perhaps others with experience don't agree.)
        I noted some references to synchronization at thread creation,
but I didn't see any formal semantics associated with this, either in
the current model or in the proposals. The same is true for
Thread.join. Lack of synchronization at either of these points would
cause the problem I see with this program.

So my questions are:

1. Am I correct that at the end, val could be 5 or 0?
  (I have sequences of load, store, etc. actions that I believe are
  correct according to JLS.)

2. If so, does this behavior seem acceptable to others?

3. Do proposals for the new JMM fix this problem (assuming it is a
  problem)? If so, could you point me to these proposals?

Thanks.

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