当前位置: 首页 > Java多线程 > 正文

Java中, 什么是 线程安全

目 录
 [ 隐藏 ]

今日偶然遭遇一个问题: 什么是 线程安全?

看到这个题目,似曾相识,细细一想,脑袋中对线程安全的概念也不是特别清楚,主要是没有一个清晰的实例在脑子中,于是打算写一个清晰的实例.在写这个例子之前,先在脑中大概过了一下,总结了什么是线程安全:

个人认为,所谓线程安全,通俗的讲,是指,一个类的所有方法在单线程调用时能够按照预先设想正常实现其功能,同时在多线程环境中,多线程同时调用该类的方法时,也能跟在单线程环境中一样能够按照预先设想正常实现其功能. 这样就可以说这个类是线程安全的.

下面这个例子中,启动了十个线程,每个线程同时工作,向一个ArrayList中插入10000个整数,完成之后,检查ArrayList的size,因为ArrayList不是线程安全的类,所有插入操作完成之后检查size发现并不是10000*10,甚至在执行过程中就抛出了异常(java.lang.ArrayIndexOutOfBoundsException).

将ArrayList 换成线程安全的 Vector类之后,结果如预期设想,十个线程每个线程插入10000个整数之后,Vector的size变成了10000*10.

针对线程不安全的类,使用同步之后,也能在多线程中安全工作.

每组测试进行10轮,因为线程安全问题有时候比较隐晦,不是每次都能显现出来,所以涉及到多线程时各种操作都要十分小心,各种坑太多了.

1.线程不安全ArrayList

package test;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Tester {

	private ArrayList<Integer> values = new ArrayList<Integer>();
	private CountDownLatch countDownLatch;
	
	public Tester(int i) {
		this.countDownLatch = new CountDownLatch(i);
	}
	
	public void test() {
		System.out.println(values.size());
	}
	
	public ArrayList<Integer> getValues() {
		return values;
	}
	
	public static void main(String[] args) {
	  int testCount = 10;
	  
	  for(int j=0;j<testCount;j++) {
	  	int runnerCount =  10;
	  	Tester myTest = new Tester(runnerCount);
	  	ExecutorService executor = Executors.newCachedThreadPool();
	  	
		  for(int i=0; i<runnerCount; i++) {
		  	executor.execute(new TesterRunner(myTest.getValues(),myTest.getCountDownLatch()));
		  }
		  executor.shutdown();
		  
		  try {
		  	myTest.getCountDownLatch().await();
		  	myTest.test();
      } catch (Exception e) {
	      
      }
	  }
  }

	public CountDownLatch getCountDownLatch() {
		return countDownLatch;
	}
}

class TesterRunner implements Runnable {

	private ArrayList<Integer> values;
	private CountDownLatch countDownLatch;
	
	public TesterRunner(ArrayList<Integer> values,CountDownLatch countDownLatch) {
		this.values = values;
		this.countDownLatch = countDownLatch;
	}
	@Override
  public void run() {
			for(int i=0;i<10000;i++) {
				values.add(i);
    }
		countDownLatch.countDown();
  }
	
}

2. 线程安全的Vector

package test;

import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Tester {

	private Vector<Integer> values = new Vector<Integer>();
	private CountDownLatch countDownLatch;
	
	public Tester(int i) {
		this.countDownLatch = new CountDownLatch(i);
	}
	
	public void test() {
		System.out.println(values.size());
	}
	
	public Vector<Integer> getValues() {
		return values;
	}
	
	public static void main(String[] args) {
	  int testCount = 10;
	  
	  for(int j=0;j<testCount;j++) {
	  	int runnerCount =  10;
	  	Tester myTest = new Tester(runnerCount);
	  	ExecutorService executor = Executors.newCachedThreadPool();
	  	
		  for(int i=0; i<runnerCount; i++) {
		  	executor.execute(new TesterRunner(myTest.getValues(),myTest.getCountDownLatch()));
		  }
		  executor.shutdown();
		  
		  try {
		  	myTest.getCountDownLatch().await();
		  	myTest.test();
      } catch (Exception e) {
	      
      }
	  }
  }

	public CountDownLatch getCountDownLatch() {
		return countDownLatch;
	}
}

class TesterRunner implements Runnable {

	private Vector<Integer> values;
	private CountDownLatch countDownLatch;
	
	public TesterRunner(Vector<Integer> values,CountDownLatch countDownLatch) {
		this.values = values;
		this.countDownLatch = countDownLatch;
	}
	@Override
  public void run() {
			for(int i=0;i<10000;i++) {
				values.add(i);
    }
		countDownLatch.countDown();
  }
	
}

3.使用synchronised同步后,非线程安全的类工作正常了

package test;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Tester {

	private ArrayList<Integer> values = new ArrayList<Integer>();
	private CountDownLatch countDownLatch;
	
	public Tester(int i) {
		this.countDownLatch = new CountDownLatch(i);
	}
	
	public void test() {
		System.out.println(values.size());
	}
	
	public ArrayList<Integer> getValues() {
		return values;
	}
	
	public static void main(String[] args) {
	  int testCount = 10;
	  
	  for(int j=0;j<testCount;j++) {
	  	int runnerCount =  10;
	  	Tester myTest = new Tester(runnerCount);
	  	ExecutorService executor = Executors.newCachedThreadPool();
	  	
		  for(int i=0; i<runnerCount; i++) {
		  	executor.execute(new TesterRunner(myTest.getValues(),myTest.getCountDownLatch()));
		  }
		  executor.shutdown();
		  
		  try {
		  	myTest.getCountDownLatch().await();
		  	myTest.test();
      } catch (Exception e) {
	      
      }
	  }
  }

	public CountDownLatch getCountDownLatch() {
		return countDownLatch;
	}
}

class TesterRunner implements Runnable {

	private ArrayList<Integer> values;
	private CountDownLatch countDownLatch;
	
	public TesterRunner(ArrayList<Integer> values,CountDownLatch countDownLatch) {
		this.values = values;
		this.countDownLatch = countDownLatch;
	}
	@Override
  public void run() {
		synchronized (values) {
			for(int i=0;i<10000;i++) {
				values.add(i);
			}
    }
		
		countDownLatch.countDown();
  }
	
}

 

 

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/java-thread/1716.html | 边城网事

该日志由 边城网事 于2015年01月19日发表在 Java多线程 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Java中, 什么是 线程安全 | 边城网事

Java中, 什么是 线程安全 暂无评论

发表评论

快捷键:Ctrl+Enter