Testing Volatile Thread Safety and Comparing LongAdder vs AtomicInteger Performance in Java
This article examines the thread‑safety of the volatile keyword under multi‑write scenarios, demonstrates its failure with a concurrent counter test, and benchmarks LongAdder against AtomicInteger using JMH, revealing LongAdder’s superior performance under high contention and AtomicInteger’s advantage in low‑contention environments.
Alibaba's "Java Development Manual" (latest Songshan edition) notes that volatile can solve visibility problems for a single‑writer‑multiple‑reader scenario but cannot guarantee thread safety when multiple threads write.
The article highlights two key points:
Non‑single‑writer scenarios such as count++ should not use volatile .
For JDK 8 and later, LongAdder is recommended over AtomicLong (or volatile ) because it offers better performance under high contention.
volatile Thread‑Safety Test
A simple program increments a volatile int count 100 000 times in the main thread while a second thread decrements it the same number of times. The expected final value is 0, but the actual result is 1063, confirming that volatile is not thread‑safe in a multi‑write environment.
public class VolatileExample {
public static volatile int count = 0; // counter
public static final int size = 100000; // loop count
public static void main(String[] args) {
// ++ 100k times in a separate thread
Thread thread = new Thread(() -> {
for (int i = 1; i <= size; i++) {
count++;
}
});
thread.start();
// -- 100k times in the main thread
for (int i = 1; i <= size; i++) {
count--;
}
// wait for the other thread to finish
while (thread.isAlive()) {}
System.out.println(count); // prints the result
}
}The test result (1063) matches the manual’s claim that volatile does not provide atomicity for multiple writers.
LongAdder vs AtomicInteger Benchmark
Using Oracle’s JMH (Java Microbenchmark Harness), the article benchmarks LongAdder against AtomicInteger under two contention levels: 1000 threads (high contention) and 100 threads (low contention). The benchmark code is:
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Benchmark)
@Threads(1000)
public class AlibabaAtomicTest {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(AlibabaAtomicTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
@Benchmark
public int atomicTest(Blackhole blackhole) throws InterruptedException {
AtomicInteger atomicInteger = new AtomicInteger();
for (int i = 0; i < 1024; i++) {
atomicInteger.addAndGet(1);
}
return atomicInteger.intValue();
}
@Benchmark
public int longAdderTest(Blackhole blackhole) throws InterruptedException {
LongAdder longAdder = new LongAdder();
for (int i = 0; i < 1024; i++) {
longAdder.add(1);
}
return longAdder.intValue();
}
}Results show that with 1000 concurrent threads, LongAdder is about 1.53× faster than AtomicInteger . With only 100 threads, AtomicInteger outperforms LongAdder , indicating that LongAdder shines under high contention because it distributes updates across multiple cells, reducing CAS retries, whereas AtomicInteger suffers from frequent CAS contention.
Conclusion
The experiments confirm that volatile is not thread‑safe for multi‑write scenarios, and that the choice between LongAdder and AtomicInteger should depend on the expected contention level: use AtomicInteger for low‑contention workloads and LongAdder for high‑contention, high‑parallelism cases.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.