This is an informal description of a new memory model based on the actions
of certain languages features: synchronization, volatiles and finals. It is
informal because I have no idea how to define it formally and because
formal models seem to end up saying more than what was intended. If anyone
can see a formal model that will match the rules I describe please pursue
Disclaimer: I have not invented any of what follows I am simply putting
things together. There are some details that others are in a better
position than I to flesh out.
The basic premise of the model is as follows:
"Any access by multiple threads to variables that are either non-final,
non-volatile or not accessed under synchronisation, can lead to results
that are surprising, if not astounding, on multi-processor systems. No
non-final, non-volatile variables should ever be accessed without
- Synchronisation maintains (approximately) its present semantics: entry to
a synchronised block acts like a "read barrier" requiring all subsequent
accesses to variables to come from main memory; exit of a synchronised
block acts like a "write barrier" requiring all modified variables to be
flushed to main memory. Instructions involving shared variables should not
be reordered across entry/exit of synchronised blocks.
- Volatile variables acquire additional memory barrier semantics. Access of
a volatile acts like a sequence: read barrier; access; write barrier.
Instructions involving shared variables can not be reordered across
accesses to volatiles. With these semantics most (all?) of the broken
"check" idioms are fixed by making the shared reference volatile.
- Final variables are guaranteed (*see caveat in note 3 below) to be seen
with their final initialised value.
Additionally we augment the Java language to allow array entries to be
declared 'final' or 'volatile'.
Complementing the above language rules we define a global safety net to be
implemented as appropriate for each VM on each platform:
"The VM must enforce the basic rules of the Java languages: incorrect
sharing of variables must not be able to break type-safety, generate
exceptions within the VM (eg incorrect vtable values), or allow a variable
(excluding long and double) to have a value that is not either the default
value or a value written by some thread to that variable." [Any others come
1. We have removed the coherence requirement from the JMM which means that
the programmer must make use of final, volatile or synchronisation when
coherence is needed.
2. We can deal with final semantics and the general safety rule by
allocating from pre-zeroed memory and placing a write barrier at the end of
construction paths. These semantics also imply the need for a read barrier
in the access path. If access to the final field is achieved by following a
volatile reference then the read barrier already exists. I talked with some
folk at OOPSLA and it was suggested that the GC level can deal with "read
barriers" for finals in a number of cases as part of the translation from
object references to physical addresses. [depends on the GC architecture of
course]. Hopefully this will alleviate most of the problems associated with
inserting read barriers.
3. We still have to deal with the escape of 'this' before 'final' fields
are assigned. Either we bar it or simply say that all bets are off. I'm
inclined to go for the latter assuming that at worst the default value of
the field will be seen.
4. To enforce these rules we will need to change a number of classes in the
core libraries (eg. String) to ensure that security can not be compromised,
by appropriate use of final and volatile. I'm a little vague on the String
security bug example (as Bill gave at OOPSLA) so I'm not sure if there are
implications concerning the finality or volatility of the individual chars
in the underlying char.
5. The removal of redundant synchronisation is an issue that I am unclear
on. I would hope that removing unnecessary synchronisation in cases where
it can be shown that only a single thread is involved, would imply that no
memory barriers are needed either. I'm less certain as to the case where
redundant synchronisation is removed but I think it too would result in
removal of memory barriers. I'm not clear how the removal of such
synchronisation and the associated barriers can be accommodated in the
model other than by slight of hand: instead of abstractly talking about
visibility wrt. main memory we could rephrase this to talk about visibility
of main memory wrt. another thread that can access the object - if no such
thread exists then no visibility rules apply.
I'll now duck for cover :-)
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:22 EDT