首页 > 代码库 > java 线程安全不线程不安全

java 线程安全不线程不安全

经常看到一些类,有的说线程安全,有的说线程不安全,顿时懵逼。

线程安全不安全,主要是在多线程执行的情况下,如果由于线程之间抢占资源而造成程序的bug即为线程不安全,下面就拿arraylist 和Vector来举个例子:

这里的arraylist 是线程不安全的,Vector是线程安全的

package Thread;import java.util.List;import java.util.concurrent.CountDownLatch;public class MyThread  implements Runnable{	private List<Object> list;	private CountDownLatch countDownLatch;	public MyThread(){}	public  MyThread(List<Object> list,CountDownLatch countDownLatch){		this.list=list;		this.countDownLatch=countDownLatch;	}	@Override	public void run() {		//给每个线程添加10个元素		for(int i=0;i<10;i++){			list.add(new Object());		}		//完成一个子线程		countDownLatch.countDown();	}}

  

package Thread;import java.util.ArrayList;import java.util.List;import java.util.Vector;import java.util.concurrent.CountDownLatch;public class ThreadTest {	/**	 * 这里要比较的是arraylist 和Vector来测试	 * arraylist 是线程不安全的	 * Vector  线程安全的	 * 	 */	public static void test(){		//用来测试的list集合		List<Object> list= new ArrayList<Object>();		//List<Object> list = new Vector<Object>();		//线程数		int threadCount =10000;		//用来让主线等待thread 个执行完毕		CountDownLatch  count=new CountDownLatch(threadCount);		for(int i=0;i<threadCount;i++){			Thread thread=new Thread(new MyThread(list, count));			thread.start();		}		try {			//主线程所有都执行完成后,再向下执行			count.await();		} catch (InterruptedException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		System.out.println(list.size());	}	public static void main(String[] args) {		for(int i=0;i<10;i++){			test();		}	}}

 运行结构:

99995
99998
99989
99973
99894
99970
99974
99977
99990
99989

当使用Vector时,即把测试的集合换一下

package Thread;import java.util.ArrayList;import java.util.List;import java.util.Vector;import java.util.concurrent.CountDownLatch;public class ThreadTest {	/**	 * 这里要比较的是arraylist 和Vector来测试	 * arraylist 是线程不安全的	 * Vector  线程安全的	 * 	 */	public static void test(){		//用来测试的list集合		//List<Object> list= new ArrayList<Object>();		List<Object> list = new Vector<Object>();		//线程数		int threadCount =10000;		//用来让主线等待thread 个执行完毕		CountDownLatch  count=new CountDownLatch(threadCount);		for(int i=0;i<threadCount;i++){			Thread thread=new Thread(new MyThread(list, count));			thread.start();		}		try {			//主线程所有都执行完成后,再向下执行			count.await();		} catch (InterruptedException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		System.out.println(list.size());	}	public static void main(String[] args) {		for(int i=0;i<10;i++){			test();		}	}}

  这样运行的结果:

100000
100000
100000
100000
100000
100000
100000
100000
100000
100000

很明显,使用Vector 这个类运行正确,这就是所谓的线程安全

当然,这只是代码层面上的,其实多线程不安全,主要因为cpu分配机制,谁获得了cpu谁就能执行,因此造成了线程的不安全.

我们可以使用synchronized  关键字来同步代码块,达到线程安全:

下面举个synchronized同步的例子:

package Thread1;public class Bank {	private int sum = 0;	public void add(int n) {		sum = sum + n;		System.out.println("sum= " + sum);	}}package Thread1;public class Cus implements Runnable {	Bank b = new Bank();	@Override	public void run() {		for (int i = 0; i < 3; i++) {			b.add(100);		}	}}package Thread1;public class Test {	public static void main(String[] args) {		Cus c = new Cus();		for (int i = 0; i < 3; i++) {			new Thread(c).start();		}	}}

  没有使用synchronized修饰的时候,运行结构是:

sum= 100
sum= 400
sum= 500
sum= 300
sum= 200
sum= 600
sum= 800
sum= 700
sum= 900

 

当然synchronized 必须要在线程运行的代码块中修饰:

package Thread1;public class Bank {	private int sum = 0;	public void add(int n) {		sum = sum + n;		System.out.println("sum= " + sum);	}}package Thread1;public class Cus implements Runnable {	Bank b = new Bank();	@Override		public void run() {		synchronized(this){			for (int i = 0; i < 3; i++) {				b.add(100);			}		}	}}package Thread1;public class Test {    public static void main (String [] args) {        Cus c = new Cus();        for(int i=0;i<3;i++){        	new Thread(c).start();        }    }}

  这样保证,每次只有一个线程在运行,结果为:

sum= 100
sum= 200
sum= 300
sum= 400
sum= 500
sum= 600
sum= 700
sum= 800
sum= 900

OK,OVER

每天进步一点点,坚持下去

 

java 线程安全不线程不安全