多執行緒-執行緒安全問題的產生原因分析以及同步程式碼塊的方式解決執行緒安全問題

ZHOU_VIP發表於2017-06-03

package cn.itcast_09;

public class SellTicket implements Runnable {
	// 定義100張票
	private int tickets = 100;
	//建立鎖物件
	private Object obj = new Object();

//	@Override
//	public void run() {
//		while (true) {
//			synchronized(new Object()){不能new,要用同一個物件
//				if (tickets > 0) {
//					try {
//						Thread.sleep(100); 
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					}
//					System.out.println(Thread.currentThread().getName() + "正在出售第"
//							+ (tickets--) + "張票");
//				}
//			}
//		}
//	}
	
	@Override
	public void run() {
		while (true) {
			synchronized (obj) {
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "張票");
				}
			}
		}
	}
}


package cn.itcast_09;

/*
 * 如何解決執行緒安全問題呢?
 * 
 * 要想解決問題,就要知道哪些原因會導致出問題:(而且這些原因也是以後我們判斷一個程式是否會有執行緒安全問題的標準)
 * A:是否是多執行緒環境
 * B:是否有共享資料
 * C:是否有多條語句操作共享資料
 * 
 * 我們來回想一下我們的程式有沒有上面的問題呢?
 * A:是否是多執行緒環境	是
 * B:是否有共享資料	    是
 * C:是否有多條語句操作共享資料	是
 * 
 * 由此可見我們的程式出現問題是正常的,因為它滿足出問題的條件。
 * 接下來才是我們要想想如何解決問題呢?
 * A和B的問題我們改變不了,我們只能想辦法去把C改變一下。
 * 思想:
 * 		把多條語句操作共享資料的程式碼給包成一個整體,讓某個執行緒在執行的時候,別人不能來執行。
 * 問題是我們不知道怎麼包啊?其實我也不知道,但是Java給我們提供了:同步機制。
 * 
 * 同步程式碼塊:
 * 		synchronized(物件){
 * 			需要同步的程式碼;
 * 		}
 * 
 * 		A:物件是什麼呢?
 * 			我們可以隨便建立一個物件試試。
 * 		B:需要同步的程式碼是哪些呢?
 * 			把多條語句操作共享資料的程式碼的部分給包起來
 * 
 * 		注意:
 * 			同步可以解決安全問題的根本原因就在那個物件上。該物件如同鎖的功能。
 * 			多個執行緒必須是同一把鎖。
 */
public class SellTicketDemo {
	public static void main(String[] args) {
		// 建立資源物件
		SellTicket st = new SellTicket();

		// 建立三個執行緒物件
		Thread t1 = new Thread(st, "視窗1");
		Thread t2 = new Thread(st, "視窗2");
		Thread t3 = new Thread(st, "視窗3");

		// 啟動執行緒
		t1.start();
		t2.start();
		t3.start();
	}
}



相關文章