1. 程式人生 > >什麼是死鎖?如何避免死鎖? 以及實現執行緒死鎖才程式

什麼是死鎖?如何避免死鎖? 以及實現執行緒死鎖才程式

死鎖是什麼

所謂死鎖:是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。由於資源佔用是互斥的,當某個程序提出申請資源後,使得有關程序在無外力協助下,永遠分配不到必需的資源而無法繼續執行,這就產生了一種特殊現象死鎖。

死鎖的必要條件

雖然程序在執行過程中,可能發生死鎖,但死鎖的發生也必須具備一定的條件,死鎖的發生必須具備以下四個必要條件

1)互斥條件:指程序對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個程序佔用。如果此時還有其它程序請求資源,則請求者只能等待,直至佔有資源的程序用畢釋放。

2)請求和保持條件:指程序已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它程序佔有,此時請求程序阻塞,但又對自己已獲得的其它資源保持不放。

3)不剝奪條件:指程序已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。

4)環路等待條件:指在發生死鎖時,必然存在一個程序——資源的環形鏈,即程序集合{P0P1P2···Pn}中的P0正在等待一個P1佔用的資源;P1正在等待P2佔用的資源,……Pn正在等待已被P0佔用的資源。

在系統中已經出現死鎖後,應該及時檢測到死鎖的發生,並採取適當的措施來解除死鎖。目前處理死鎖的方法可歸結為以下四種:

預防死鎖

  這是一種較簡單和直觀的事先預防的方法。方法是通過設定某些限制條件,去破壞產生死鎖的四個必要條件中的一個或者幾個,來預防發生死鎖。預防死鎖是一種較易實現的方法,已被廣泛使用。但是由於所施加的限制條件往往太嚴格,可能會導致系統資源利用率和系統吞吐量降低。

避免死鎖

  該方法同樣是屬於事先預防的策略,但它並不須事先採取各種限制措施去破壞產生死鎖的的四個必要條件,而是在資源的動態分配過程中,用某種方法去防止系統進入不安全狀態,從而避免發生死鎖。(安全狀態、銀行家演算法)

檢測死鎖

  這種方法並不須事先採取任何限制性措施,也不必檢查系統是否已經進入不安全區,此方法允許系統在執行過程中發生死鎖。但可通過系統所設定的檢測機構,及時地檢測出死鎖的發生,並精確地確定與死鎖有關的程序和資源,然後採取適當措施,從系統中將已發生的死鎖清除掉。(死鎖定理化簡資源分配圖)

解除死鎖

  這是與檢測死鎖相配套的一種措施。當檢測到系統中已發生死鎖時,須將程序從死鎖狀態中解脫出來。常用的實施方法是撤銷或掛起一些程序,以便回收一些資源,再將這些資源分配給已處於阻塞狀態的程序,使之轉為就緒狀態,以繼續執行。死鎖的檢測和解除措施,有可能使系統獲得較好的資源利用率和吞吐量,但在實現上難度也最大。(資源剝奪法,撤銷程序法,程序回退法)

用兩個執行緒請求被對方佔用的資源,實現執行緒死鎖

/**
 * 用兩個執行緒請求被對方佔用的資源,實現執行緒死鎖
 */
public class DeadLockThread implements Runnable {
	private static final Object objectA = new Object();
	private static final Object objectB = new Object();
	private boolean flag;

	@Override
	public void run() {
		String threadName = Thread.currentThread().getName();
		System.out.println("當前執行緒 為:" 
		+ threadName + "\tflag = " + flag);
		if (flag) {
			synchronized (objectA) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(threadName 
						+ "已進入同步程式碼塊objectA,準備進入objectB");
				synchronized (objectB) {
					System.out.println(threadName 
							+ "已經進入同步程式碼塊objectB");
				}
			}

		} else {
			synchronized (objectB) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(threadName 
						+ "已進入同步程式碼塊objectB,準備進入objectA");
				synchronized (objectA) {
					System.out.println(threadName 
							+ "已經進入同步程式碼塊objectA");
				}
			}
		}
	}

	public static void main(String[] args) {
		DeadLockThread deadlock1 = new DeadLockThread();
		DeadLockThread deadlock2 = new DeadLockThread();
		deadlock1.flag = true;
		deadlock2.flag = false;
		Thread thread1 = new Thread(deadlock1);
		Thread thread2 = new Thread(deadlock2);
		thread1.start();
		thread2.start();

	}

}
當前執行緒 為:Thread-0	flag = true
當前執行緒 為:Thread-1	flag = false
Thread-1已進入同步程式碼塊objectB,準備進入objectA
Thread-0已進入同步程式碼塊objectA,準備進入objectB


http://blog.csdn.net/joejames/article/details/37960873

http://www.cnblogs.com/XHJT/p/3898970.html