Syntax
AtomicInteger counter = new AtomicInteger(0);Examples
AtomicInteger Basics
Thread-safe increment and decrement without a synchronized block.
import java.util.concurrent.atomic.AtomicInteger;
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // atomically adds 1, returns new value
counter.incrementAndGet();
counter.addAndGet(5); // atomically adds 5
System.out.println(counter.get()); // 7Comparing to a Non-Atomic Counter
Why AtomicInteger matters: a plain int shared across threads is not safe to increment without extra synchronization.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
AtomicInteger safeCounter = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 1000; i++) {
executor.submit(safeCounter::incrementAndGet);
}
executor.shutdown();
// safeCounter will reliably reach 1000 - a plain "int count" shared this way
// could lose increments due to race conditions between threadscompareAndSet()
The atomic building block: only updates the value if it currently matches an expected value.
import java.util.concurrent.atomic.AtomicInteger;
AtomicInteger value = new AtomicInteger(10);
boolean updated = value.compareAndSet(10, 20); // succeeds: current value was 10
System.out.println(updated); // true
System.out.println(value.get()); // 20
boolean failed = value.compareAndSet(10, 30); // fails: current value is now 20, not 10
System.out.println(failed); // false
System.out.println(value.get()); // still 20Best practices
- Use atomic classes instead of a synchronized block when you only need to protect a single variable - they are typically faster due to lock-free implementation
- Use incrementAndGet()/getAndIncrement() rather than manually reading, adding, and writing back a value across separate atomic operations
- Reach for a synchronized block or a Lock instead when you need to atomically update more than one related variable together
- Remember atomic classes only guarantee safety for the operations they provide directly - wrapping several atomic calls together does not make the whole sequence atomic
At a glance
- Purpose
- General-purpose application development
- File extension
- .java
- Runs in
- Java Virtual Machine
- Usually used with
- JDK and Java libraries
Specifications & further reading
Related Java documentation
Creating Threads (Thread & Runnable)
A thread is an independent path of execution within a program, letting multiple tasks run seemingly simultaneously. Java offers two main ways to create a thread: extending the Thread class directly and overriding its run() method, or implementing the Runnable interface and passing it to a Thread - the Runnable approach is generally preferred, since Java doesn't support multiple inheritance and Runnable keeps your class free to extend something else.synchronized Keyword
The synchronized keyword prevents multiple threads from executing a block of code (or a method) at the same time on the same object, protecting shared, mutable data from race conditions. When one thread enters a synchronized block, it acquires a lock on the specified object; any other thread trying to enter a synchronized block on that same object must wait until the lock is released.ExecutorService & Thread Pools
ExecutorService, from java.util.concurrent, manages a pool of reusable threads, letting you submit tasks without manually creating and managing individual Thread objects. This avoids the overhead of constantly creating new threads and gives you control over how many run concurrently. Executors provides convenient factory methods for common pool configurations, like a fixed-size pool or a single-threaded executor.Thread Control: sleep, join, interrupt
Java provides several methods for coordinating and controlling thread execution. Thread.sleep() pauses the current thread for a specified duration. join() makes the calling thread wait until another thread finishes before continuing. interrupt() signals a thread that it should stop what it's doing, a cooperative mechanism the target thread must actively check for and respond to.
A thread is an independent path of execution within a program, letting multiple tasks run seemingly simultaneously. Java offers two main ways to create a thread: extending the Thread class directly and overriding its run() method, or implementing the Runnable interface and passing it to a Thread - the Runnable approach is generally preferred, since Java doesn't support multiple inheritance and Runnable keeps your class free to extend something else.synchronized Keyword
The synchronized keyword prevents multiple threads from executing a block of code (or a method) at the same time on the same object, protecting shared, mutable data from race conditions. When one thread enters a synchronized block, it acquires a lock on the specified object; any other thread trying to enter a synchronized block on that same object must wait until the lock is released.ExecutorService & Thread Pools
ExecutorService, from java.util.concurrent, manages a pool of reusable threads, letting you submit tasks without manually creating and managing individual Thread objects. This avoids the overhead of constantly creating new threads and gives you control over how many run concurrently. Executors provides convenient factory methods for common pool configurations, like a fixed-size pool or a single-threaded executor.Thread Control: sleep, join, interrupt
Java provides several methods for coordinating and controlling thread execution. Thread.sleep() pauses the current thread for a specified duration. join() makes the calling thread wait until another thread finishes before continuing. interrupt() signals a thread that it should stop what it's doing, a cooperative mechanism the target thread must actively check for and respond to.