1. 程式人生 > >Java多執行緒2.1.多執行緒之死鎖

Java多執行緒2.1.多執行緒之死鎖

多執行緒之死鎖

1、鎖物件Lock

雖然我們可以理解同步程式碼塊和同步方法的鎖物件問題,但是我們並沒有直接看到在哪裡加上了鎖,在哪裡釋放了鎖。

為了更清晰的表達如何加鎖和釋放鎖,JDK5以後提供了一個新的鎖物件Lock。

  • Lock:是一個介面
    • void lock()
    • void unlock()
  • ReentrantLock:Lock介面的一個具體實現類

2、同步弊端:

  • 效率低
  • 如果出現了同步巢狀,就容易產生死鎖問題

3、死鎖問題及其程式碼演示:

  • 是指兩個或者兩個以上的執行緒在執行的過程中,因爭奪資源產生的一種互相等待的現象
  • 同步程式碼塊的巢狀案例

(1)建立執行緒類

package cn.itcast_02;

public class DieLock extends Thread {

	private boolean flag;

	public DieLock(boolean flag) {
		this.flag = flag;
	}

	@Override
	public void run() {
		if (flag) {
			synchronized (MyLock.objA) {
				System.out.println("if objA");
				synchronized (MyLock.objB) {
					System.out.println("if objB");
				}
			}
		} else {
			synchronized (MyLock.objB) {
				System.out.println("else objB");
				synchronized (MyLock.objA) {
					System.out.println("else objA");
				}
			}
		}
	}
}

(2)建立鎖

package cn.itcast_02;

public class MyLock {
	// 建立兩把鎖物件
	public static final Object objA = new Object();
	public static final Object objB = new Object();
}

(3)測試執行緒類

package cn.itcast_02;

/*
 * 同步的弊端:
 * 		A:效率低
 * 		B:容易產生死鎖
 * 死鎖:
 * 		兩個或兩個以上的執行緒在爭奪資源的過程中,發生的一種相互等待的現象。
 * 舉例:
 * 		中國人,美國人吃飯案例。
 * 		正常情況:
 * 			中國人:筷子兩支
 * 			美國人:刀和叉
 * 		現在:
 * 			中國人:筷子1支,刀一把
 * 			美國人:筷子1支,叉一把
 */
public class DieLockDemo {
	public static void main(String[] args) {
		DieLock dl1 = new DieLock(true);
		DieLock dl2 = new DieLock(false);

		dl1.start();
		dl2.start();
	}
}

(4)兩個執行緒使用各自的鎖,出現了問題:

  • 執行緒dl1使用鎖A輸出一句話“if objA”,然後被執行緒dl2搶去了CPU資源而被迫阻塞;
  • 此時執行緒dl2使用鎖B輸出一句話“else objB”,然後又被執行緒dl1搶去了CPU資源而被迫阻塞;
  • 這時,執行緒dl1想繼續執行下一句話,但是需要鎖B,而鎖B這時候被執行緒dl2佔用著,所以又被迫阻塞;
  • 這時,如果執行緒dl2又搶到了CPU資源想繼續向下執行的話,但是需要正在被執行緒dl1佔用的鎖A,所以又被迫阻塞;
  • 依次產生死鎖問題。