多執行緒-買電影票出現了同票和負數票的原因分析

ZHOU_VIP發表於2017-06-03

package cn.itcast_08;

public class SellTicket implements Runnable {
	// 定義100張票
	private int tickets = 100;

	@Override
	public void run() {
		while (true) {
			// t1,t2,t3三個執行緒
			// 這一次的tickets = 100;
			if (tickets > 0) {
				// 為了模擬更真實的場景,我們稍作休息
				try {
					Thread.sleep(100); // t1就稍作休息,t2就稍作休息
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "張票");
				// 理想狀態:
				// 視窗1正在出售第100張票
				// 視窗2正在出售第99張票
				// 但是呢?
				// CPU的每一次執行必須是一個原子性(最簡單基本的)的操作。
				// 先記錄以前的值
				// 接著把ticket--
				// 然後輸出以前的值(t2來了)
				// ticket的值就變成了99
				// 視窗1正在出售第100張票
				// 視窗2正在出售第100張票

			}
		}
	}
	
	@Override
	public void run() {
		while (true) {
			// t1,t2,t3三個執行緒
			// 這一次的tickets = 1;
			if (tickets > 0) {
				// 為了模擬更真實的場景,我們稍作休息
				try {
					Thread.sleep(100); //t1進來了並休息,t2進來了並休息,t3進來了並休息,
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "張票");
				//視窗1正在出售第1張票,tickets=0
				//視窗2正在出售第0張票,tickets=-1
				//視窗3正在出售第-1張票,tickets=-2
			}
		}
	}
}


package cn.itcast_08;

/*
 * 實現Runnable介面的方式實現
 * 
 * 通過加入延遲後,就產生了兩個問題:
 * A:相同的票賣了多次
 * 		CPU的一次操作必須是原子性的
 * 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();
	}
}


相關文章