We began this chapter by looking at race conditions and saw the need for synchronization, in real life situations as well as in concurrent code. We had a detailed look at race conditions and saw the role that the volatile keyword plays.
Next, we looked at the singleton pattern, which represents a program's global state. We saw how to safely share the state using monitors. We also correct visibility semantics and looked at an optimization called double-checked locking. We also saw how the initialization on demand holder design pattern resolves these problems.
We looked at a use case, a concurrent set implementation, using sorted linked lists. Using locks could lead to coarse-grained locking. Though semantically correct, this scheme allows only a single thread, and this could hurt concurrency.
The solution was to use the hand-over-hand design pattern. We studied it in depth, thereby understanding how explicit locking can give us a better solution, preserving the correctness and also...