Home  Synchronization and concurrency  wait/notify  final  volatile  synchronized keyword  Java threading  Deadlock (and avoiding it)  Java 5: ConcurrentHashMap  Atomic variables  Explicit locks  Queues  Semaphores  CountDownLatch  CyclicBarrier

Atomic field updaters

The Java 5 atomic classes also include atomic field updaters. These are essentially used as "wrappers" around a volatile field (primitive or object reference). In truth, these wrappers are used inside the Java class libraries, but probably aren't used much in user code. But it is worth taking a look at them to see when they could be useful. They are generally used when one or both of the following are true:

  • You generally want to refer to the variable "normally" (that is, without having to always refer to it via the get or set methods on the atomic classes) but occasionally need an atomic get-set operation (which you can't do with a normal volatile field);
  • you are going to create a large number of objects of the given type, and don't want every single instance to have to have an extra object embedded in it just for atomic access.

An example of the first kind is BufferedInputStream. Every instance of BufferedInputStream contains an internal buffer, defined as a volatile byte array. Generally speaking, BufferedInputStream just needs to refer to this array "normally" for the purpose of reading/writing bytes. However, an atomic get-and-set operation is needed in specific places where the buffer array is replaced (either to grow it or to mark it as null or closed), because closure can occur in a different thread to that performing the reads. One option would have been to declare the buffer variable as an AtomicReference to an array, and always get and set the array via this variable. But that would be a bit messy. Instead, a noraml volatile array variable is used, and the class also contains a static AtomicReferenceUpdater as follows:

static AtomicReferenceFieldUpdater<BufferedInputStream, byte[]>
  bufUpdater = AtomicReferenceFieldUpdater.newUpdater
        (BufferedInputStream.class,  byte[].class, "buf");

The array itself still remains a normal (volatile) variable, and reads and writes from the array can use normal array syntax. But when necessary, via the field updater, an atomic compare-and-set operation can be performed on the volatile variable. Although the updater is static, each instance of BufferedInputStream has its own buffer of course. So when we perform the CAS operation, we need to pass into the updater the actual object whose variable we want to affect:

if (bufUpdater.compareAndSet(this, oldBuffer, newBuffer)) {
  ...
}

This is a call inside a method of BufferedInputStream, so this refers to the particular instance of this class that the method is being called on, and that object's variable will be affected.

Using atomic field updaters for linked nodes

Another use for atomic field updaters is to avoid creating a large number of spurious atomic variables. For example, if we were creating a linked list structure designed for concurrent access, we might want each node to have an atomic variable pointing to the next node in the list. Judicious code can then allow different parts of the list to be updated concurrently. Without atomic field updaters, this would have meant code such as the following:

public class Node<T> {
  private AtomicReference<Node<T>> next;
  private T val;
  ...
}

In other words, every single node will have an additional AtomicReference object embedded in it. Using an atomic field updater, we can get a performance gain by declaring the 'next node' variable as a normal volatile object reference, and then using a field updater (of which we declare a single, static, instance shared by all nodes to access their respective 'next node' field):

public class Node<T> {
  private volatile Node<T> next;
  private T val;
  ...
}

As mentioned, atomic field updaters have been used in various places in the Java class libraries. In reality, if you want an efficient currently accessible data structure, it is strongly recommended to use one of the excellent standard implementations such as ConcurrentHashMap, ConcurrentLinkedQueue or (as of Java 6) ConcurrentSkipListMap.

Next...

On the next page, we move on to look at Java 5's concurrent collections, with arguably the most important, the ConcurrentHashMap class.

Article written by Neil Coffey (@BitterCoffey).

Software

 LetterMeister (word puzzle game for iPhone)
 Currency Quoter (currency converter/predictor)
 French Vocab Games for iPhone/iPad
 Vocabularium: create Spanish vocab podcasts


Java programming articles and tutorials on this site are written by Neil Coffey (@BitterCoffey). Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles, or if you simply have a programming question that you would like to see answered on this site. Most topics will be considered. But in particular, the site aims to provide tutorials and information on topics that aren't well covered elsewhere, or on Java performance information that is poorly described or understood. Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Neil Coffey 2014. All rights reserved.