上期文章講到「i++;」自己是一個線程不安全的操做,緣由是操做不是原子性的,存在取值和賦值的兩個過程,可是究竟怎麼會不安全呢?本期藉助一個「vmlens」的項目來演示爲什麼會發生線程不安全的狀況。文末是vmlens簡介。java
測試代碼:git
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 ); } }
重要的是pom.xml文件配置:apache
<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>
接下來是vmlens的報告: api
從圖中咱們能夠看出在兩個線程同時執行「i++;」的時候,兩個線程都前後讀取到了i的值「0」,而後前後完成了計算「i+1」,最後又前後給i賦值「1」,致使測試用例執行失敗。安全
介紹一下這個插件: 「vmlens」是一款測試java多線程的工具。markdown
下面是做者托馬斯原文:多線程
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
做者本人照片:app
歡迎有興趣的童鞋一塊兒交流less