Nearly all of the decisions that I (and probably you) don't want to
have to make about final and volatile semantics surround the fact that
one cannot now declare that elements of an array are final or
volatile.
This underlying problem could be fixed. But there are lots of
arguments for not changing the language syntax to do so. Instead, I'd
like to get on the table a proposal to create simple array-holding
classes with special semantics.
For volatile, here's the int version. (Seven others just like it
would be required: byte, short, char, long, float, double, Object.)
final class java.lang.VolatileIntArray {
VolatileIntArray(int capacity); // initialize to all-zeros
VolatileIntArray(int[] elements); // initialize as copy of array
VolatileIntArray(int[] elements, int offset, int size); // sub-array version
int length();
int get(int i);
void set(int i, int value);
int[] toArray(); // return copy
}
The semantics are that initialization/get/set of each element acts in
the same way as read/write from a volatile field.
For final:
final class java.lang.FinalIntArray {
FinalIntArray(int[] elements); // initialize as copy
FinalIntArray(int[] elements, int offset, int size); // sub-array version
int length();
int get(int i);
int[] toArray(); // return copy
}
The semantics are that initialization/get of each element acts in
the same way as a final field.
There are no multidimensional versions. People would have to
do this manually. It's not hard. For example:
VolatileObjectArray matrix = new VolatileObjectArray(nrows);
for (int i = 0; i < nrows; ++i)
matrix.set(i, new VolatileFloatArray(ncols));
(Element extraction would sometimes require ugly casts, but this may be
addressed by generics proposal.)
All-in-all, this is not much less convenient to use than would
be special syntax for marking array elements as final or volatile.
Compilers would be required to have special knowledge of these
classes. In addition to properly maintaining semantics, this enables
some optimizations that will typically lead to them being just as fast
as raw arrays. In particular, they would not always need to make
array copies in constructors when they could determine that the
intialization arrays isn't otherwise used. And in many cases, they
could inline these objects as parts of their enclosing objects and
thus save on GC, indirection, etc overhead. And so on.
Some JDK classes would need to be rewritten to use this. Offhand
though, the number of classes for which this would be critical
seems pretty small. String, for sure.
The main advantages I can see for this approach are that the memory
model rules become easier to understand, implement, enforce, and agree
upon:
1. The ordinary rules for final become the ones Bill listed
as being uncontroversial:
* If you read a final field, you are guaranteed to see the value set
in the constructor unless:
* The object escapes before the constructor finishes
* The thread constructing the object reads the field before it is
written
* Native code or reflection is used to change the field
* This guarantee is enforced regardless of data races.
2. The ordinary rules for volatile most likely become the ones
associated with Bill's V1-V2; that is, no automatic propagation
of volatileness down one or more levels of indirection.
The disadvantages I know of are:
1. It would require revision of some core classes. (However,
some revision seems inevitable in any case.)
2. Just adding a "volatile" or "final" here and there would
not fix as many existing broken programs as it would if
the most liberal versions of final and volatile were adopted.
Any others? Are these compelling?
-- Doug Lea, Computer Science Department, SUNY Oswego, Oswego, NY 13126 USA dl@cs.oswego.edu 315-341-2688 FAX:315-341-5424 http://gee.cs.oswego.edu/ ------------------------------- JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:24 EDT