Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java VarHandle: atomic transitions and explicit access modes

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A VarHandle provides typed access to a variable with selected memory-order and atomic-update operations; its access mode is part of the operation contract.

Download Java source kit

This program targets Java 11 without preview flags. Use a full JDK for compiler-based examples.

A transition is narrower than a workflow

A receipt begins unclaimed. One worker attempts to change its state from zero to one. compareAndSet makes that conditional transition indivisible for the selected field. A second claim against zero fails after the first succeeds, so the caller can reject duplicate work without a separate read-then-write race.

This is not an entire processing transaction. After the claim, a network operation can fail or the process can stop. The application still needs a recovery state and an idempotent external operation. Atomic ownership of one field does not supply either of those.

Choose the access mode deliberately

Plain, opaque, acquire/release and volatile modes offer different ordering rules. Reading a state with acquire requires an appropriate publication protocol; it does not turn unrelated unsynchronized writes into a valid design by naming the mode. The program uses compareAndSet and getVolatile to show a simple atomic state change without claiming to prove every weaker-mode protocol.

A handle includes receiver and value types. For an instance integer field, passing a different receiver or a long value can produce a type error at invocation. The lookup also follows access-control rules. Resolve the handle once and keep the field contract visible near the state definition.

Working program

Java
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public class ClaimedReceiptState {
    private volatile int state;
    private static final VarHandle STATE;
    static {
        try { STATE = MethodHandles.lookup().findVarHandle(ClaimedReceiptState.class, "state", int.class); }
        catch (ReflectiveOperationException failure) { throw new ExceptionInInitializerError(failure); }
    }
    public static void main(String[] args) {
        ClaimedReceiptState receipt = new ClaimedReceiptState();
        System.out.println(STATE.compareAndSet(receipt, 0, 1));
        System.out.println(STATE.compareAndSet(receipt, 0, 1));
        System.out.println((int) STATE.getVolatile(receipt));
    }
}

Output

Output
true
false
1

Costs and boundaries

The example performs three bounded field operations. Under contention, the hardware and runtime determine retry and ordering costs; a CAS-based retry loop can consume work without making a system-wide latency guarantee. Use this primitive when its ownership protocol is simpler to explain than an ordinary lock, not merely because it avoids the word synchronized.

Common Mistakes

  • Do not use plain access when the publication rule requires ordered access.
  • Weak CAS variants can fail without an observed value change.
  • One CAS does not commit several unrelated structures.

Read next

Java memory model, Atomic values, Multi-index ownership.

java
varhandles
Storage details