Fundamentals 7 min read

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, using a simple multithreaded test and the vmlens tool to visualize the conflicting accesses and explain the underlying thread‑safety issue.

FunTester
FunTester
FunTester
Why i++ Is Not Thread‑Safe: A Hands‑On Demo with vmlens

Why i++ is not thread‑safe

The expression i++ consists of a read of the variable, an increment, and a write back. These three steps are performed separately, so two threads can interleave the operations. If both threads read the same initial value, each computes the same incremented value and both write that value, resulting in a lost update.

Demonstration test

public class TestCounter {
  private volatile int i = 0;

  @Interleave
  public void increment() {
    i++; // non‑atomic increment
  }

  @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); // expected value if increment were atomic
  }
}

Maven configuration for the vmlens interleave plugin

The project must include the vmlens plugin and the required test dependencies. Only the essential sections are shown.

<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>
          <trimStackTrace>false</trimStackTrace>
          <includes>
            <include>com.vmlens.examples.doNotCombine.TestCounter</include>
          </includes>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Executing the test and interpreting the vmlens report

Run the test with Maven (e.g., mvn test). The vmlens interleave plugin instruments the bytecode, inserts synchronization points, and records the order in which threads access shared variables. After the run, it generates an HTML report.

The report shows that both threads read the initial value 0, each computes 0 + 1, and both write back 1. Consequently the final value of i is 1, and the assertion assertEquals(2, i) fails, confirming the race condition.

vmlens report screenshot
vmlens report screenshot

Technical overview of vmlens

vmlens is a Java testing tool that systematically explores thread interleavings. It works by:

Instrumenting the compiled classes to insert wait points at each memory access and monitor acquisition.

Running the test repeatedly, each time forcing a different scheduling of the inserted wait points.

Detecting data races, deadlocks, and other concurrency anomalies from the observed schedules.

Providing a visual report that highlights conflicting accesses, enabling developers to reduce shared state or add proper synchronization.

Using vmlens together with the Maven interleave plugin allows reproducible detection of subtle concurrency bugs such as the non‑atomic i++ example shown above.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javatestingmaventhread safetymultithreadingvmlens
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.