Home | FAQ | Contact me

Atomic References in Java

I've used atomic references a lot in writing NiFi processors, but there's a lot I don't know about the topic—just the stuff I've used. Here's an excerpt from something I stumbled upon once that makes for good notes useful in the future. This isn't well enough written to be one of my topics, but it serves the purpose of a good note.

AtomicReference

In essence, AtomicReference wraps another class, here Thread.State, to add atomic update functionality to that class. The compareAndSet() method only updates the atomic variable to RUNNING when the current value is (still) NEW.

public final class CommandReader
{
  private static final String                          THREAD_NAME   = "surefire-forkedjvm-command-thread";
  private static final CommandReader                   READER        = new CommandReader();
  private final        Thread                          commandThread = newDaemonThread( new CommandRunnable(), THREAD_NAME );
  private final        AtomicReference< Thread.State > state         = new AtomicReference<>( NEW );

  public static CommandReader getReader()
  {
    final CommandReader reader = READER;

    if ( reader.state.compareAndSet( NEW, RUNNABLE ) )
      reader.commandThread.start();

    return reader;
  }
}

If we test this code thus:

public static void main( String[] args )
{
  out.println( VM.current().details() );
  out.println( ClassLayout.parseClass( AtomicReference.class ).toPrintable() );
  out.println( ClassLayout.parseClass( Thread.State.class ).toPrintable() );
}

...we see:

# Running 64-bit HotSpot VM.
java.util.concurrent.atomic.AtomicReference object internals:
Instance size: 16 bytes
java.lang.Thread$State object internals:
Instance size: 24 bytes

AtomicReferenceFieldUpdater

...uses reflection to access the field to be updated atomically:

// (compare this code to the block above...)

private volatile     Thread.State                                                        state                = NEW;
private static final AtomicReferenceFieldUpdater< AtomicReferenceExample, Thread.State > ATOMIC_STATE_UPDATER =
                                AtomicReferenceFieldUpdater.newUpdater( AtomicReferenceExample.class,
                                                                    Thread.State.class,
                                                                    "state" );
public void update()
{
  ATOMIC_STATE_UPDATER.compareAndSet( this, NEW, RUNNABLE );
}

VarHandle

This appears only in Java 9 (in replacement for sun.misc.Unsafe).

private volatile     Thread.State state = NEW;
private static final VarHandle    ATOMIC_STATE_UPDATER;
static
{
  try
  {
    MethodHandles.Lookup lookupHandle = MethodHandles.lookup();

    ATOMIC_STATE_UPDATER = lookupHandle.findVarHandle( VarHandleExample.class, "state", Thread.State.class );
  }
  catch( ReflectiveOperationException e )
  {
    throw new Error( e );
  }
}

public void update()
{
  ATOMIC_STATE_UPDATER.compareAndSet( this, NEW, RUNNABLE );
}