快看,i++真的不安全

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

  1. 须要测试多个线程访问相同内存位置或监视器的应用程序的全部部分。vmlens显示多个线程访问相同内存位置或监视器的全部位置。
  2. vmlens插入等待,在测试期间通知指令并从新运行测试,直到测试全部线程交错。这与数据竞争和死锁的自动检测一块儿致使系统和可重复的测试。
  3. 经过查看多个线程以何种方式访问​​相同状态,您能够减小共享状态的数量。
  4. 较少共享状态意味着须要较少的同步监视器。

下面是做者托马斯原文:多线程

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

相关文章
相关标签/搜索