Re: JavaMemoryModel: Re: Are this$x fields final?

From: Jerry Schwarz (jerry.schwarz@oracle.com)
Date: Thu May 27 2004 - 18:05:23 EDT


At 02:17 PM 5/27/2004, Bill Pugh wrote:

>On May 27, 2004, at 1:33 PM, Jerry Schwarz wrote:
>
>> At 09:24 PM 5/26/2004, Sylvia Else wrote:
>>
>>Consider this contrived scenario
>>
>>public class Outer {
>> final int[] x = new int[1];
>>
>> class Inner {
>> Inner() {
>> x[0] = 42;
>> }
>>
>> int get() {
>> return x[0];
>> }
>> }
>> }
>>
>> static Outer.Inner inner;
>> Thread 1
>> Outer outer = new Outer();
>> inner = outer.new Inner();
>>
>> Thread 2
>>
>> int r = inner.get();
>>
>> Behaviour in question: r == 0;
>>
>> If the reference to the outer class is final, then the behaviour is
>> prohibited, otherwise it is permitted. So which should it be?
>>
>>
>>
>> Permitted. There is no reason to treat this any differently than
>>
>> class Outer {
>> static int[] x = new int[1];
>> }
>>
>> class Inner {
>> Inner() {
>> Outer.x[0] = 42;
>> }
>> int get() {
>> return Outer.x[0];
>> }
>> }
>>
>
>
>There is a difference in the semantics. Remember that (correct) reads of
>final fields
>are not only guaranteed to see the value the final field is initialized
>to, but
>also get transitive guarantees.

Yes I understood that. What I was trying to say was that I don't think we
want to provide the transitive guarantees for inner classes. I agree that
the compiler must guarantee that the correct value of the implicit pointer
(i.e. this$0) is always seen. What I disagree with is the idea that because
we need that guarantee it makes sense to give the stronger transitive
closure guarantee for the rest of the actions of the Inner constructor.

With regards to this$0 itself I would want a very strong guarantee. Namely
that it is never seen to be null.

class Outer {
     int x = 29;
     static Inner inner;

     class Inner {
         int y = 17;
         Inner() {
             inner = this;
         }
         int get() { return x + y; }
     }
}

Thread 1:
Outer o = new Outer();
Inner i = o.new Inner();

Thread 2:
Inner ri = i;
if ( ri != null ) r = ri.get();

I want a guarantee that ri.get() will not throw a
NullPointerException. Not only do I want this$0 to be treated as "final".
I want it to be treated as "volatile" so that the assignment to it
(presumably at the beginning of the constructor) is seen by Thread 2. But
I'm fine with the value of r being 0, 17, 29 or 48.

>If this$0 is final, you can't get r = 0, assuming that
>the reference through an inner object is the only way the thread
>performing get() gains access
>to the memory allocated for the x array. This is due to the transitive
>guarantees for final fields.
>
>

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



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