用同步機制解決多線程併發所產生的問題

/*
 * 解決線程併發問題
 */
package com.test.thread;

public class Test1 {
	public static void main(String []args){
			//創建一個售票窗口
		TicketWindow tw1 = new TicketWindow();
		
		Thread t1 = new Thread(tw1);
		Thread t2 = new Thread(tw1);
		Thread t3 = new Thread(tw1);
			//三個線程啓動售票
		t1.start();
		t2.start();
		t3.start();
	
	}
}

class TicketWindow implements Runnable{
	private int tickets = 1000;

	@Override
	public void run() {
		// TODO 自動生成的方法存根
		
		while(true){	
				//同步代碼塊
			//synchronized(this){
				if(tickets>0){
					System.out.println(Thread.currentThread().getName()+"賣出第"+tickets+"張票");
					tickets--;
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO 自動生成的 catch 塊
						e.printStackTrace();
					} 
				}else{
					break;
				}
			// }//同步代碼塊
		}
		
	}
}
若註釋掉sychronized(Object)語句的,執行結果如下:

Thread-0賣出第1000張票
Thread-2賣出第999張票
Thread-1賣出第998張票
Thread-0賣出第997張票
Thread-1賣出第996張票
Thread-2賣出第996張票
Thread-0賣出第994張票
Thread-2賣出第993張票
Thread-1賣出第993張票
Thread-0賣出第991張票

多線程併發,給我們的編程帶來很多,提高程序效率,同時也會帶來線程安全的問題。如以上情況,在出現線程併發時,會導致出現多次售出同一張票的情況,去掉sychronized(Object)語句的註釋則不會出現以上情況。

對同步機制的解釋

java任意類型的對象都有一個標誌位(用術語來講,可以稱爲對象鎖),該標誌位具有0,1兩種狀態,其開始狀態爲1,當某個純種執行到了sychronized(Object)語句後,objec對象的標誌爲變爲0的狀態,直到執行完整個sychronized語句中的代碼塊後,該對象的標誌位又回到1狀態。

當一個線程執行到sychronized(Object)語句的時候,先檢查object對象的標誌位,如果爲0狀態,表明已經有另外的純種正在執行sychronized代碼塊內中的代碼,那麼這個線程將暫時阻塞,讓出cpu資源,直到另外的線程執行完相關的同步代碼,並將object對象的標誌位變爲1狀態, 這個線程的阻塞就會被取消,線程能繼續運行,該線程又會將object的標誌爲變0狀態,防止其他線程再進入相關的同步代碼塊中。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章