Problems with the Java 1.4 synchronization model

Java's bread-and-butter means of synchronizing data– the synchronized method– has some advantages. It's reasonably easy to understand and implement, and generally allows you to write thread-safe code without getting too bogged down in the details of what the JVM does "under the hood" to synchronize data. Of course, this is also one of its potential downfalls– a failure to understand exactly what synchronized does has led to programmers using incorrect idioms such as "double-checked locking" or the notion that "you only need to synchronize on the write, not the read". But even in a perfect world where every programmer fully understands the synchronized keyword, as a method of synchronization it has some shortcomings:

A limitation of pre-Java 5 as a platform is that the standard class library doesn't provide implementations of some common synchronization idioms. For example, a common use of synchronization in server applications is to manage a shared resource pool (for example, of database connections). Rather than a simple lock, what we really need in this case is a "permission" system that says "allow up to N threads to hold a lock at any one time" (because there are N resources available in the pool). Idioms such as this can of course be constructed pre Java 51 (else nobody would have been using Java to run servers!) but not necessarily very efficiently. And without a standard library implementation, different programmers have been forced to re-invent the wheel, possibly in buggy ways.

So how does Java 5 improve this situation? On the next pages, we look at Synchronization under the hood, and how Java 5 improves on it.

Notes:
1. For some suggested pre-Java 5 implementations of idioms such as barriers, sempahores etc, see Wellings, A. (2004), Concurrent and Real-Time Programming in Java.