On Apr 19, 2004, at 6:36 PM, Sylvia Else wrote:
> At 03:06 PM 19/04/2004 -0400, Bill Pugh wrote:
>
>> class A {
>> static A g;
>> long x;
>> protected void finalize() {
>> g = this;
>> long r1 = x;
>> // ...
>> }
>> }
>>
>>
>> Thread 1:
>> A r2 = new A();
>> r2.x = 1;
>> r2.x = -1;
>>
>> Thread 2:
>> do {
>> r3 = A.g;
>> } while (r3 == null);
>> r4 = r3.x;
>>
>> Are we guaranteed that r1 and r4 will both see the value -1?
>>
>> At a intuitive level, before running the finalizer on an object o,
>> we need to make sure that if two conflicting writes w1 and w2
>> have been performed to a field/element of o, and w1 happens-before
>> w2, then we need to make sure that before the finalizer is run, the
>> write w1 becomes no longer accessible.
>
> Yet there is data race on the accesses to g, and no happens-before
> edge that prevents r4 = 1. This outcome looks no different from other
> counter-intuitive outcomes that arise from naive multi-threaded
> programming. Is there any reason to treat this one as special?
>
> As so often here, I'm left wondering whether I've missed the point.
>
The point is that most finalizers are not synchronized.
So declaring them all to be broken is a big step we'd like to avoid.
So I think we need to ensure that r1 will be equal to -1.
What about r4? I'm not sure. If A.g was volatile, I think we
would need to ensure that r4 is -1. After all, if the finalizer
thread is guaranteed to see -1, and the finalizer thread passes
the object to another thread in some correctly synchronized
way, then that other thread should also see -1 for o.x.
But what if A.g is non-volatile. Perhaps it shouldn't be guaranteed,
although unfortunately that will complicate the semantics.
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:01:05 EDT