Java Locks and Atomicity

It's important not to confuse people by using words that are imprecise or ambiguous. This annoys many experts because this world is confusing enough. I will point my fingers to the "misuse" of the word atomic. I have to be careful here because I had the idea for this post when I was reading the bible of concurrency: Java Concurrency in Practice. However, in this book, just for instance, the word atomic is used in a way, which can confuse people that spent five years of their career building transactional database systems. In short:

In Java, only single, discrete language operations are ever going to be atomic. There is no such concept in Java that inherently creates atomicity.

Assigning a value to a variable is an atomic operation in Java. Calling a method (the call itself) or creating an object may be atomic, but the atomic data types like AtomicInteger  provide atomic actions. There are more examples. However, if one tries to explain the notion of Java locks by giving the impression they make compound language operations atomic, then this is not 100 percent correct. Locks can make sure that the sequence of language operations are going to be performed in isolation to other concurrent threads working with that same resource. That's exactly what locks like  ReentrantLock and ReentrantReadWriteLock add to the language features. 

Sharing Mutable Objects Using a Safe Accessor Service

On page 54 in his distinguished book "Java Concurrency In Practice," Brian Goetz describes how objects can be safely shared across threads. He lists four options:

  • The object is thread-confined, meaning updates to the object are performed by only one owning thread
  • The object is shared read-only, meaning this object only needs one-time publication
  • The object is inherently thread-safe, meaning it performs synchronization internally
  • The object is guarded by some lock

In this post, I will describe a variant that falls into the fourth category. The objects shared are not thread-confined, not read-only, and aren't synchronized internally. I am going to use a read-write lock to guard the object's state. As the presented technique is highly concurrent, it will not require synchronized blocks and gauruntees that no needless thread contention will slow down application performance. Without using synchronized, it is still garanteed that any change will be visible across all threads that share the object instances; this is achieved by applying certain rules to the shared objects' mutable state.

Lazy Initialization Singleton Idioms

Frequently, I face requirements where I would like to use a singleton bean instead of creating new objects — and this happens all of the time. Beans that have no relevant state or are expensive to create lend itself to become a singleton. The conventional singleton idioms are fairly easy and go something like this:

// private constructor singleton idiom
public class PrivateConstructorSingleton {
   public static final PrivateConstructorSingleton INSTANCE = new PrivateConstructorSingleton();
   private PrivateConstructorSingleton() {}
}
// lazy loading singleton idiom
public static class LazyLoadingSingleton {
   private LazyLoadingSingleton() {}
   private static class LazyHolder {
       static final LazyLoadingSingleton INSTANCE = new LazyLoadingSingleton();
   }
   public static LazyLoadingSingleton getInstance() {
       return LazyHolder.INSTANCE;
  }
}