上期文章讲到“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