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

每天進步一點點,堅持下去

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM