Understanding the Java Memory Model
Writing correct multithreaded Java programs requires developers to know the Java Memory Model (JMM) which is specified in JSR 133 [1]. Intuitive assumptions related to the value of mutable shared variables do not hold when there are multiple threads reading/writing the variables. The value written to a shared variable by one thread may not be immediately visible to other threads reading that shared variable due to many underlying details like compilers’ instruction reordering, or cache effects. In order to guarantee timely visibility of a shared variable, a program has to correctly synchronize access to mutable shared variables.
The memory model is specific to a processor architecture, and it describes how threads can interact through the memory, and specifically what value a memory read operation may return. In fact the memory model defines a happens-before relationship such that if action A happens-before action B, then the writes of A is visible to B. The aim of the synchronization primitives is to establish happens-before relationships between actions. For example, a write to a volatile variable happens-before every subsequent read of that variable. To give a concrete example from Brian Goetz’s talk [2] who is the author of the book Java Concurrency in Practice, Thread A executes:
while (!asleep) ++sheep;
where Thread B sets the asleep variable. So a compiler may think that the asleep variable is loop-invariant, and for optimization purposes it may take the evaluation of that variable out of the loop:
if (!asleep)
{
while (true) ++sheep;
}
unless asleep variable is declared as volatile.
Here is another nice example from Jeremy Manson’s blog [2] who is one of the authors of the JSR 133:
0: x == y == 0
Thread 1:
1: r1 = x;
2: y = 1;
Thread 2:
3: r2 = y;
4: x = r2;
In this example is it possible that r1==r2==1? Yes ! Remember that compilers can reorder statements of a program. In such a case the order of execution may be 0-2-3-4-1 resulting in r1==r2==1. To prevent such surprising results we have to use synchronization.
To summarize, if there are reads/writes to a shared variable by different threads, than to guarantee the visibility, we should use appropriate synchronization primitives. Luckily with Java 1.5 there is a huge package java.util.concurrent devoted to simplify multi-threaded programming. For further reading, I recommend you to check the JSR 133 FAQ [5].
[1] http://jcp.org/en/jsr/detail?id=133
[2] http://wiki.bejug.org/confluence/display/JP05/The+new+Java+Memory+Model
[3] http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1630.pdf
[4] http://jeremymanson.blogspot.com/2007/08/causality-and-java-memory-model.html
[5] http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
About this entry
You’re currently reading “ Understanding the Java Memory Model ,” an entry on Sirius ICT
- Published:
- 10.5.09 / 3pm
- Category:
- Blog, Development Issues, Thougths and Reflections
No comments
Jump to comment form | comments rss [?] | trackback uri [?]