4.2.3 Atomic Variables Explained
Atomic Variables in Java are a powerful tool for ensuring thread-safe operations on shared variables. They provide a way to perform atomic operations, which are operations that appear to execute instantaneously from the perspective of other threads. Understanding atomic variables is crucial for developing high-performance, concurrent applications.
Key Concepts
1. Atomicity
Atomicity refers to the property of an operation that appears to be instantaneous and indivisible from the perspective of other threads. In the context of atomic variables, atomic operations ensure that the operation completes successfully without interference from other threads.
2. Atomic Classes
Java provides several atomic classes in the java.util.concurrent.atomic
package, such as AtomicInteger
, AtomicLong
, AtomicBoolean
, and AtomicReference
. These classes provide methods to perform atomic operations on their respective types.
Example
import java.util.concurrent.atomic.AtomicInteger; public class AtomicExample { private AtomicInteger counter = new AtomicInteger(0); public void increment() { counter.incrementAndGet(); } public int getCount() { return counter.get(); } }
3. Atomic Operations
Atomic operations are methods provided by atomic classes that ensure the operation is performed atomically. Common atomic operations include get()
, set()
, incrementAndGet()
, decrementAndGet()
, and compareAndSet()
.
Example
AtomicInteger atomicInt = new AtomicInteger(5); int currentValue = atomicInt.get(); // Atomic read atomicInt.set(10); // Atomic write int incrementedValue = atomicInt.incrementAndGet(); // Atomic increment boolean wasSet = atomicInt.compareAndSet(11, 20); // Atomic compare and set
4. Compare-And-Swap (CAS)
Compare-And-Swap (CAS) is a fundamental technique used in atomic operations. It compares the current value of a variable with an expected value and, if they are equal, updates the variable to a new value. CAS is used in methods like compareAndSet()
.
Example
AtomicInteger atomicInt = new AtomicInteger(5); boolean success = atomicInt.compareAndSet(5, 10); // CAS operation if (success) { System.out.println("Value was updated to 10"); } else { System.out.println("Value was not updated"); }
Examples and Analogies
Think of atomic variables as secure vaults in a bank. Each vault (atomic variable) ensures that only one transaction (atomic operation) can occur at a time. This prevents conflicts and ensures that the bank's records (shared variables) are always accurate and up-to-date. For example, when depositing money (incrementing a counter), the vault ensures that the deposit is completed in one smooth, uninterrupted action.
By using atomic variables, you can avoid the complexities of traditional synchronization mechanisms like locks and monitors, making your concurrent code more efficient and easier to manage.