Look, i++ is really not safe

Posted by loopt on Mon, 22 Jul 2019 10:53:17 +0200

Last article mentioned that "i++;" itself is a thread unsafe operation, because the operation is not atomic, there are two processes of value and assignment, but how can it be unsafe? This issue uses a "vmlens" project to demonstrate why thread insecurity occurs. At the end of the paper is a brief introduction to vmlens.

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 );
	}	
}

Importantly, the pom.xml file configuration:

<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>

  <name>examples</name>
  <url>http://maven.apache.org</url>

 <pluginRepositories>
  <pluginRepository>
    <id>vmlens</id>
    <url>http://vmlens.com/download</url>
  </pluginRepository>
</pluginRepositories>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <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>
    <pluginManagement>
    <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>
    </plugins>
 </pluginManagement>
 
  <plugins>
  			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>3.0.0-M3</version>
				<configuration>
					<includes>
						<include>none</include>
					</includes>
				</configuration>
			</plugin>
 	<plugin>
				<groupId>com.vmlens</groupId>
				<artifactId>interleave</artifactId>
				<version>1.0.4</version>
				<!-- start regression test -->
				<configuration>
					<trimStackTrace>false</trimStackTrace>
									<includes>
		<include>com.vmlens.examples.doNotCombine.TestCounter</include>
					</includes>
				</configuration>
           </plugin>
      </plugins>
  </build>
  </project>

Next comes the vmlens report:

From the figure we can see that when two threads execute "i+;", both threads read the value of "0" of I successively, then completed the calculation of "i+1" successively, and finally assigned "1" to I successively, which led to the failure of test case execution.

Introduce this plug-in: "vmlens" is a tool for testing java multithreading.

  1. Multiple threads need to be tested to access all parts of an application with the same memory location or monitor. vmlens show multiple threads accessing the same memory location or all locations of the monitor.
  2. vmlens inserts wait, notifies instructions during the test and reruns the test until all threads are interleaved. Together with data competition and deadlock detection, this leads to system and repeatable testing.
  3. By looking at how multiple threads access the same state, you can reduce the number of shared states.
  4. Less shared state means fewer synchronous monitors.

The following is the original article by Thomas:

Hello!

Do you love to write bug-free software? Me too!

It always bothers me when I can not test something. That's why I created vmlens, a tool to test multithreaded java.

Now 4 years and countless tests later vmlens enables you to test multi-threaded java systematic and reproducible. And like vmlens now let my completely test vmlens, vmlens let you test the multithreaded part of your application

Enjoy writing concurrent software secured by tests.

Cheers, Thomas

Author's photo:

Interested children's shoes are welcome to communicate with each other.

Topics: Programming Maven Apache Java Junit