Why a Simple Increment Fails in Multithreaded Java: A Concurrency Demo
This article explains atomicity, thread safety, and race conditions in Java by walking through a concrete example where multiple threads increment a shared volatile variable, showing why the non‑atomic i++ operation leads to inconsistent results.
The article introduces three core concepts for concurrent programming:
Atomicity : an operation (or group of operations) must execute completely without interruption, or not at all.
Thread safety : when multiple threads access a class, proper locking ensures that only one thread can modify protected data at a time, preventing inconsistent or polluted state.
Thread‑unsafe : lack of protection can cause "dirty" data when threads interleave their reads and writes.
To be thread‑safe, a class’s public methods must be atomic so that other threads can only observe the state before or after a method call. The following Java example demonstrates why a seemingly simple increment is not atomic.
public class TR extends FanLibrary {
private volatile int i = 0;
public void ss() {
sleep(100); // added to increase the chance of race condition
i++; // not atomic
}
@Before
public void be() {
output("before");
}
@Test
public void sdfa() throws InterruptedException {
Thread first = new Thread(() -> { ss(); });
Thread second = new Thread(() -> { ss(); });
first.start();
second.start();
first.join();
second.join();
output(i);
}
@After
public void ds() {
output("after");
}
}Running the test may produce console output similar to:
INFO-> before
INFO-> 1
INFO-> afterThe increment statement i++ expands to i = i + 1, which consists of two separate steps: reading the current value and writing the incremented value back. When two threads read i as 0 simultaneously, both compute the new value 1 and each writes 1, so the final value remains 1 instead of the expected 2. This race condition shows that i++ is not an atomic operation and the method ss() is therefore thread‑unsafe.
To achieve thread safety, the increment must be performed atomically, for example by using AtomicInteger or synchronizing the method.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
