next up previous
Next: A New Proposal Up: Fixing the Java Memory Previous: The Java Memory Model

Subsections

Reality

We would like the Java memory model to interfere as little as possible with compiler optimizations and to not require memory barrier instructions on hardware with loose memory models, such as the Sparc V9 Relaxed Memory Order (RMO) [WG94].

Here are some of the issues that drive us to weaken the memory model. All of these are in the absence of explicit synchronization:

1.
We want to give the compiler/optimizer freedom to reorder instructions that could be reordered in a single threaded environment.
2.
We want to allow the compiler/optimizer to do forward substitution / scalar replacement (e.g., replace a getfield instruction with a reuse of the value last stored into that variable).
3.
We want to allow the processor to reorder instructions during execution.
4.
We want to allow the processor to use a write-buffer.
As it turns out, issue 1 is largely equivalent to issue 3, and issue 2 is largely equivalent to issue 4.

Instruction Reordering

In memory models such as the Sparc-V9 Relaxed Memory Order (RMO) [WG94, Chap. 8], the processor execute instructions out of order, so long as it does so in a way that would not be detectable in absence of any shared memory interaction with other processors. In doing so, the processor is allowed to rename registers (allowing it to ignore output and anti dependences on registers) and perform control-speculation on loads so as to reduce the ordering constraints. However, it does have to respect output and anti dependences for memory locations.


  
Figure 7: Execution only possible due to write buffer
\begin{figure}\begin{center}
\begin{tabular}{\vert c\vert c\vert}
\multicolumn{...
...icolumn{2}{c}{Anomalous result: x = z = 2}
\end{tabular}\end{center}\end{figure}

Write Buffers

The memory models for most processors ignore the cache: instructions can be reordered, but when the instructions execute, they update main memory immediately (this is, of course, only a model). Directly following this model would be expensive, so most memory models are relaxed further by allowing a write buffer. When a write is initiated, it goes into the write buffer. The write is not considered to actually occur until it reaches main memory. If a read occurs for a memory location in the write buffer, the read gets the value in the memory buffer. In essence, this allows the processor to ignore flow dependences on memory locations when reordering instructions, and yet still get the right answer. Figure 7 shows a program execution legal only due to the existence of a write buffer in the memory model (without a write buffer, flow dependences would order the statements in each thread).

Coherence is difficult

As noted above, the existing Java memory model enforces Coherence. Unfortunately, Coherence cannot be enforced on architectures such as Sparc RMO without memory barriers. The Sparc RMO doesn't not guarantee that reads of the same memory location will be executed in their original order. To enforce this, a load/load memory barrier is required between any two successive loads of the same memory location. It is unclear if any existing implementations of the Sparc RMO would actually violate Coherence.

As mentioned earlier (Section 2.3), Coherence also interferes with a number of compiler optimizations.

   
Flushing memory is expensive

The semantics of the lock and unlock actions in the JMM are that they cause a thread to flush all dirty variables from the thread's working memory (registers, cache, ...) to main memory, and a lock action also causes a thread empty all variables from the thread's working memory, so that they have to be reloaded from main memory before they can be used.

Some have suggested that, particularly in a multiprocessor server, this will be expensive. An alternative would be to say that only memory accessed inside the synchronized block is flushed/emptied. This would probably be a good idea if you were designing a memory model from scratch, although more analysis is needed. However, people writing to the current memory model might expect that

synchronized(unsharedObject) {}

would have the effect of a memory barrier. Careful thought is required about the amount of existing code that would break if this change were made.


next up previous
Next: A New Proposal Up: Fixing the Java Memory Previous: The Java Memory Model
William Pugh