Why i++ Is Not Thread‑Safe: A Hands‑On Demo with vmlens
This article demonstrates how the non‑atomic i++ operation can cause race conditions in Java by using the vmlens tool to visualize thread interleavings, providing sample test code, Maven configuration, and an analysis of the resulting report.
In the previous post we noted that the expression i++ is not thread‑safe because it consists of separate read‑modify‑write steps, but we did not show exactly how the race occurs. This article uses the open‑source tool vmlens to illustrate the problem.
Test code :
public class TestCounter {
private volatile int i = 0;
@Interleave
public void increment() {
i++;
}
@Test
public void testUpdate() throws InterruptedException {
Thread first = new Thread(() -> increment());
Thread second = new Thread(() -> increment());
first.start();
second.start();
first.join();
second.join();
}
@After
public void checkResult() {
assertEquals(2, i);
}
}The pom.xml must contain the vmlens plugin and its dependencies. The essential parts are shown below:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vmlens</groupId>
<artifactId>examples</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<pluginRepositories>
<pluginRepository>
<id>vmlens</id>
<url>http://vmlens.com/download</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>com.vmlens</groupId>
<artifactId>annotation</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.vmlens</groupId>
<artifactId>interleave</artifactId>
<version>1.0.4</version>
<configuration>
<includes>
<include>com.vmlens.examples.doNotCombine.TestCounter</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>Running the test with the vmlens plugin produces a report (see image) that shows both threads reading the initial value 0, each computing 0 + 1, and then both writing back 1. Consequently the final assertion that i == 2 fails, demonstrating the race condition.
About vmlens : it is a Java multithreading testing tool that can monitor all accesses to shared memory locations or monitors, insert waits to explore different interleavings, and automatically detect data races and deadlocks. By visualizing how threads interact with shared state, developers can reduce the amount of shared data and the need for synchronization.
The author, Thomas, summarizes his motivation: "I created vmlens to enable systematic, reproducible testing of multithreaded Java code, helping developers write concurrent software that is verified by tests."
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.
