Synchronization under the hood, and why Java 5 improves it (ctd)

(Continued from our discussion of Java synchronization under the hood.)

Exposure of atomic instructions in Java 5

Having worked through this example, we can see that the synchronized block involves an awful lot of baggage just to increment an integer variable. And paradoxically, the underlying implementation actually uses a machine code instruction designed to atomically update an integer variable! Rather than using CAS instructions around a whole load of other lock housekeeping tasks, wouldn't it be great if we could just use a CAS instruction to update the count variable? That way we do away with having to waste memory and time on extra housekeeping variables and with having to ensure memory access conditions on variables that are never affected by trhe critical block of code. In the worst case, our code just loops a couple of times rather than being context-switched out for several milliseconds to wait for a simple variable increment. Java 5 effectively allows this.

The big synchronization breakthrough in Java 5 is that it effectively exposes atomic instructions such as CAS to the Java programmer. The java.util.concurrent package contains the AtomicInteger class (and similar classes for other data types) allowing us to atomically compare-and-set an integer (and variants such as increment-and-get, set-and-get etc). Classes such as AtomicInteger are essentially wrappers around atomic machine code instructions such as CAS.

For a simple counter class such as the one above, we can pretty much use AtomicInteger as a drop-in replacement. But what's even more interesting is that Java 5 includes a whole host of other synchronization and concurrency classes already built around this new atomic functionality.

On the next page, we start our of Java 5 concurrency features by looking at the atomic classes in Java 5.

Tightening up of volatile and final

The introduction of non-blocking atomic variable access is a key part of the Java 5 concurrency improvements. Another improvement which is easy to miss is that the definitions of volatile and final have been tightened up slightly in order to allow them to be used with a couple of common programming idioms: lazy initialisation and immutable objects. As of Java 5:

We'll look at what this means in more detail below, but first let's get back to the atomic classes.