Synchronization, the Java Memory Model, and other tricky bits, part one
I’m not sure how many of you caught all the concurrency changes introduced in Java 5. Java 5 was indeed the release that added some new features to help multithreaded applications run efficiently. If you haven’t kept up with these developments, this article will serve as a short introduction.
Java Memory Model
The Java Memory Model (JMM) defines the relationship between a program’s variables and how they’re stored in and retrieved from the computer’s memory. The JMM is part of the Java Language Specification, and in practice developers don’t need to know it in detail. Its semantics do, however, have several implications that every developer needs to understand when working on a multithreaded application.
I say several, but there are really two things that matter. One is the visibility of variables across threads, and the other is the reordering of reads and writes. A variable lives in memory, but various performance optimizations can kick in while it’s in use. For example, its value might be stored in a local cache or a CPU register. HotSpot, the JVM’s runtime compiler, can make these optimizations, and the hardware can make them too. The JMM defines how these optimizations may affect the way Java variables behave, particularly across threads.
Many developers who use synchronized to address concurrency problems focus on one aspect of the keyword, atomicity through mutual exclusion in a critical section. But synchronized is also concerned with whether variables are visible to other threads and in what order they can be read or written. That’s where it ties directly into the JMM.
class Reordering {
int x = 0, y = 0;
public void writer() {
x = 1;
y = 2;
}public void reader() {
int r1 = y;
int r2 = x;
}
}Imagine two threads working with the code above. Say one of them runs thewritermethod, and right after it the other thread starts running reader. It’s wrong to assume that executingint r1 = y;(r1 == 2) automatically means thatr2 == 1. The first thread, or more precisely the compiler, may have reordered the two statements if doing so didn’t affect that thread’s execution. Another possibility is that the thread runningreadersees and works with cached values ofx,y.
The following keyword also prevents those statements from being reordered and makes the current values visible across all threads:synchronized.Synchronizedmeans, in JMM terms, that acquiring a lock reads fresh values from main memory and releasing it writes them back. Nor can an optimization leave memory in an inconsistent state within a synchronized block. Withsynchronized, threads always see the actual state of memory.
If you’re wondering how Java 5 fits in, it addresses some ambiguities and gaps in the JMM specification. Under the previous JMM, before Java 1.5, a thread could see an object that wasn’t fully initialized. See double checked locking. Likewise, two threads could see the same final variable in different states.Another change in the JMM specification is the expanded semantics for variables declaredvolatile.Volatileon a variable means a thread must always access that variable in main memory. The old model, however, allowed an access to avolatilevariable to be reordered relative to an ordinary variable access.
class Reordering {
int x = 0
volatile y = 0;
public void writer() {
x = 1;
y = 2;
}public void reader() {
if(y == 2) {
//x ==1
}
}
}Under the revised JMM in Java 1.5, the semantics ofvolatileguarantee that a thread can also see the preceding changes to memory.Volatilenow has the same effects on visibility and reordering assynchronized.
The new JMM is covered in full by JSR 133, but I recommend starting with one of the following articles. They’re easier for the average developer to follow.
In the next article we’ll turn to topics closer to everyday development, including alternatives to synchronization offered by the java.util.concurrent package and its nonblocking algorithms.Related articles
Related CZ Podcast episodes
- #3 · Java 6 SE, Vývoj webových aplikací
Dagi and Filemon discuss Java 6 and web application frameworks. · Czech audio
- #1 · Vývojová prostředí v Javě
The first CZ Podcast episode looks at Java development environments. · Czech audio