1. 程式人生 > >java執行緒死鎖例項

java執行緒死鎖例項

死鎖發生的四個必要條件:

    1、互斥使用,即當資源被一個執行緒使用(佔有)時,別的執行緒不能使用
    2、不可搶佔,資源請求者不能強制從資源佔有者手中奪取資源,資源只能由資源佔有者主動釋放。
    3、請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資源的佔有。
    4、迴圈等待,即存在一個等待佇列:P1佔有P2的資源,P2佔有P3的資源,P3佔有P1的資源。這樣就形成了一個等待環路。
上面四個條件同時成立時就會產生死鎖,如果消除任何一個條件就可以消除死鎖。

下面是一個死鎖發生的例項:

package com.cy.test;

public class Sisuo {

	public static Object object1;
	public static Object object2;

	public static class MyRunnable implements Runnable {
		int flag;

		public MyRunnable(int flag) {
			this.flag = flag;

		}

		@Override
		public void run() {
			if (flag == 1) {
				synchronized (object1) {
					for(int i=0;i<10000;i++);//擴大死鎖發生機率
					//或者Thread.sleep(50);
					synchronized (object2) {
						System.out.println("1");
					}
				}
			} else if (flag == 2) {
				synchronized (object2) {
					for(int i=0;i<10000;i++);
					//或者Thread.sleep(50);
					synchronized (object1) {
						System.out.println("2");
					}
				}
			}
		}

	}

	public static void main(String[] args) {

		object1 = new Object();
		object2 = new Object();
		new Thread(new MyRunnable(1)).start();
		new Thread(new MyRunnable(2)).start();

	}
}
上面的例項在執行時會發生死鎖,也就是兩個執行緒分別等待另一個執行緒釋放資源,但另一個執行緒被synchronized關鍵字修飾,不能直接釋放資源,所以造成的結果就是相互等待,程式直接掛掉了。

下面主要分析一下發生死鎖的原因:

從上面的程式來看,改程式主要使用了兩把鎖,分別是執行緒1對資源object1佔有資源的同時又對object2申請資源,並想佔有,同時執行緒2對資源object2佔有資源的同時又對object1申請資源,如果我們刪除兩個鎖之間的迴圈語句,最後得到的結果可能是能正常執行的,那麼為什麼這種情況沒有死鎖呢,其實是因為cpu的執行速度非常快,此時執行緒1佔有了資源object1,並很快又佔據資源object2,此時執行緒2想要申請object2的時候,資源已經被執行緒1佔有,所以此時等待執行緒1執行完畢,最後輸出的結果就會是12或者21,但是如果在兩個鎖之間加了運算稍微大的運算,那麼最後的結果就是執行緒1已經佔據資源object1,執行緒2已經佔據資源object2,此時執行緒1申請資源object2時,已經被執行緒2佔有,而此時執行緒2申請資源object1時又被執行緒1佔有,此時兩者都不能釋放各自佔有的資源,因為用synchronized關鍵字所修飾,所以最後的結果就會是相互等待而系統直接掛掉