In concurrent programming, shared mutable state is dangerous without proper synchronization. Java’s java.util.concurrent.atomic
package introduces atomic variables — lightweight, lock-free classes that provide safe operations on single variables.
This tutorial explores core atomic classes, how they work, and when to use them.
🚀 What Are Atomic Variables?
Atomic variables are thread-safe wrappers for primitive types and references. They ensure operations like increment, set, compare-and-set (CAS) are atomic and non-blocking.
These classes use low-level hardware primitives (CAS) to perform updates without locks.
🔧 Common Atomic Classes
Class | Description |
---|---|
AtomicInteger | Atomic operations on int values |
AtomicLong | Atomic operations on long values |
AtomicBoolean | Atomic true/false flags |
AtomicReference |
Atomic updates to object references |
AtomicStampedReference |
Reference with version control |
🧠 Java Memory Model & CAS
Atomic variables leverage the compare-and-swap (CAS) operation for thread safety. This works by checking if the current value equals the expected value, and if so, swapping it with a new one.
This avoids locking and ensures visibility and atomicity in most scenarios.
✍️ Syntax Examples
AtomicInteger
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // Atomic increment
count.get(); // Read value
count.compareAndSet(5, 10); // CAS update
AtomicReference
AtomicReference<String> name = new AtomicReference<>("initial");
name.set("updated");
String current = name.get();
name.compareAndSet("updated", "final");
✅ Benefits of Atomic Variables
- Lock-free (non-blocking)
- Fast under low contention
- Avoids deadlocks and thread starvation
- Guarantees visibility like
volatile
- Provides atomicity without
synchronized
⚠️ Limitations
- Not suitable for compound operations across multiple variables
- CAS retries can cause performance issues under high contention
- Can lead to ABA problems (fixed with
AtomicStampedReference
)
👷 Real-World Use Cases
- Thread-safe counters
- Flags (e.g.,
isShutdown
,hasStarted
) - Shared configurations or context updates
- Concurrent task status tracking
🆚 Atomic Variables vs Synchronized
Feature | Atomic Variables | synchronized/locks |
---|---|---|
Performance | Faster (non-blocking) | Slower (blocking) |
Code complexity | Moderate | Simple |
Use for compound ops | ❌ | ✅ |
Deadlock risk | ❌ | ✅ |
Visibility guarantee | ✅ | ✅ |
📌 What's New in Java Concurrency (8–21)
- Java 8:
LongAdder
for high-throughput counters,CompletableFuture
- Java 9: VarHandles for low-level atomic operations
- Java 11: Improved async programming support
- Java 21: Virtual threads, scoped values, structured concurrency
🛠 Best Practices
- Use atomic variables only for single-variable updates.
- Prefer
LongAdder
orLongAccumulator
for high-concurrency counting. - Document CAS use clearly.
- Avoid mixing atomic and synchronized code.
❓ FAQ
-
What is compare-and-swap (CAS)?
A technique to update a value only if it matches an expected one. -
When should I use AtomicInteger?
For thread-safe counters without locking. -
Can I replace synchronized with AtomicReference?
Only if you're modifying one variable or reference. -
What is ABA problem?
A reference changes from A → B → A and is falsely considered unchanged. -
How to fix ABA issues?
UseAtomicStampedReference
orAtomicMarkableReference
. -
Do atomic classes guarantee visibility?
Yes — they act like volatile fields. -
What’s the difference between LongAdder and AtomicLong?
LongAdder reduces contention under high load. -
Are atomic operations truly lock-free?
Yes, but under the hood, they use CPU-level atomic instructions. -
Can I use AtomicInteger in parallel streams?
Yes, but beware of performance bottlenecks. -
Should I prefer atomic classes for everything?
No — use them where their scope fits; prefer higher-level tools for complex tasks.
🧾 Conclusion and Key Takeaways
- Atomic variables offer thread-safe, lock-free operations on single values.
- They use CAS to ensure atomicity and visibility without blocking.
- Best suited for flags, counters, and reference updates.
- Pair them with proper understanding of the Java Memory Model and thread safety patterns.
Mastering atomic variables enables efficient and safe concurrent programming in modern Java.