Re: JavaMemoryModel: Thread starting in constructors

From: Jerry Schwarz (jschwarz@us.oracle.com)
Date: Tue Mar 12 2002 - 10:46:24 EST


At 07:57 PM 3/11/2002, Joshua Bloch wrote:
>Bill,
>
> > OK, this is just a simple example of something I'm trying to fine tune:
> >
> > class A {
> > int x;
> > final int y;
> > public A(int a, int b) {
> > x = a;
> > y = b;
> > new Thread() {
> > public void run() {
> > System.out.println("x = " + x + ", y = " + y);
> > }}.start();
> > }
> > }
> >
> > Assume someone invokes new A(1,2). Which of the might occur?
> >
> > a) prints x = 1, y = 2
> > b) prints x = 0, y = 0
> > c) prints x = 0, y = 2
> > d) prints x = 1, y = 0
> > e) the thread started in the constructor throws a NullPointerException
>
> Clearly I'm being dense here, but why is anything other than (a) legal?
>I always thought that there was implicit synchronization between a thread
>that started a thread and the thread that it started. If anything besides
>(a) is legal, people will be mightily confused.
> Josh

That was my reaction too, but I slept on it overnight and I think I see a
subtlety that I overlooked yesterday. When is A.y read? Could it be read
by the constructor of the Thread instead of by the run method.

This question can be illustrated without threads. Consider the following
example

   public class S {
     public final int x;
     S() { x = ... ; }
     ...
   }

   public class U {
     private S s;
     public U(S s) { this.s = s; }
     public int f() { return s.x; }
   }

Is a compiler allowed to transform the definition of U into

   public class U' {
     private int s_x;
     public U(S s) { this.s_x = s.x ; }
     public int f() { return s_x; }
   }

Obviously, this couldn't be allowed if s.x were not final, but does the
special semantics of final allow it? I would like to say yes because this
is potentially a significant optimization. The relevance to Bill's example
is that if this transformation were allowed on the anonymous Thread class then

> d) prints x = 1, y = 0

becomes possible.

But so do other anomalies. In particular what if U's are used in
constructors of S. Let's modify S a little

   public class S {
     public final int x;
     private U u;
     public S() {
       u = new(this);
       x = ...; // non-zero value
     }
     public int f() { return u.f(); }
   }

With the optimization in place S.f will return 0. But I don't see any way
I can justify S.f returning 0, so I guess the optimization can't be
allowed. And so, (d) isn't allowed either.

   -- Jerry Schwarz

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



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