I was thinking about the semantics for final fields, and came up with
a slightly disturbing example.
class Foo {
final int x;
static Foo p,q;
Foo(int i) {
x = i;
p = this;
}
}
Thread 1:
Foo.q = new Foo(42);
Thread 2:
Foo a = Foo.p;
if (a != null && a.x == 0) {
Foo b = Foo.q;
if (a == b) {
int i = a.x;
int j = b.x;
// is it possible for j to be zero?
System.out.println(i+j);
}
}
OK, in thread 2, the local variable a might contain an improperly
published reference to a Foo, so a.x might be zero. No big surprise.
However, the local variable b can only contain a reference to a
properly published reference to a Foo, so a read of b.x should return
the value set in the constructor (42).
This means the compiler must not perform this analysis/transformation:
* Since I know a == b, a.x and b.x reference the same memory location.
* I already read a.x, and know that it contains zero.
* I haven't done any synchronization, so I can reuse zero as the
value of b.x.
Does it bother anyone that this analysis/transformation will be
illegal for final fields? Basically, just because you have two
aliased references to the same final field through two different
pointers, you can't assume reads will return the same value, because
one pointer may be correctly published and the other not.
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:37 EDT