1. 程式人生 > >Java執行緒死鎖及解決方案

Java執行緒死鎖及解決方案

要了解執行緒死鎖,首先要明白什麼是死鎖

死鎖

通俗點講:死鎖就是兩個或兩個以上的程序或執行緒在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。


用簡單一點的例子來說吧


比如這個交通堵塞的例子,從圖中可以看到四個方向行駛的汽車互相阻塞,如果沒有任何一個方向的汽車退回去,那麼將形成一個死鎖

上述圖中有產生死鎖的四個原因:

1.互斥條件:一個資源每次只能被一個執行緒使用。圖上每條路上只能讓一個方向的汽車通過,故滿足產生死鎖的條件之一

2.請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。可以看出,圖上每個方向的汽車都在等待其他方向的汽車撤走,故滿足產生死鎖的條件之二

3.不剝奪條件:程序已獲得的資源,在未使用完之前,不能強行剝奪。這裡假設沒有交警,那麼沒有人能強行要求其他方向上的汽車撤離,故滿足產生死鎖的條件之三

4.迴圈等待條件:若干程序或執行緒之間形成一種頭尾相接的迴圈等待資源關係。這個在圖中很直觀地表達出來了

死鎖Java程式碼小例子
package huaxin2016_9_9;

public class ThreadDeadlock {
	public static void main(String[] args) throws InterruptedException {
		Object obj1 = new Object();
		Object obj2 = new Object();
		Object obj3 = new Object(); 
		//新建三個執行緒
		Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1"); 
		Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2"); 
		Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3"); 
		//讓執行緒依次開始
		t1.start(); 
		//讓執行緒休眠
		Thread.sleep(5000);
		t2.start();
		Thread.sleep(5000);
		t3.start();
	} 
} 
class SyncThread implements Runnable{ 
	private Object obj1; 
	private Object obj2;
	//建構函式
	public SyncThread(Object o1, Object o2){ 
		this.obj1=o1;
		this.obj2=o2;
	} 
	@Override
	public void run() {
		//獲取並當前執行執行緒的名稱
		String name = Thread.currentThread().getName();
		System.out.println(name + " acquiring lock on "+obj1);
		
		
		synchronized (obj1) { 
			System.out.println(name + " acquired lock on "+obj1); 
			work();
			System.out.println(name + " acquiring lock on "+obj2); 
			synchronized (obj2) { 
				System.out.println(name + " acquired lock on "+obj2); 
				work();
		    } 
			System.out.println(name + " released lock on "+obj2); 
	    } 
		System.out.println(name + " released lock on "+obj1); 
		System.out.println(name + " finished execution.");
	}
	private void work() { 
		try { 
			Thread.sleep(30000); 
		} 
		catch (InterruptedException e) { 
			e.printStackTrace();
		}
	} 
}
上述死鎖小例子執行結果為
t1 acquiring lock on [email protected]
t1 acquired lock on [email protected]
t2 acquiring lock on [email protected]
t2 acquired lock on [email protected]
t3 acquiring lock on [email protected]
t3 acquired lock on [email protected]
t1 acquiring lock on [email protected]
t2 acquiring lock on [email protected] t3 acquiring lock on [email protected]
可以很直觀地看到,t1、t2、t3都在要求資源,卻都保持自己的資源,故而引起死鎖

解決方案:

1.打破互斥條件,我們需要允許程序同時訪問某些資源,這種方法受制於實際場景,不太容易實現條件;

2.打破不可搶佔條件,這樣需要允許程序強行從佔有者那裡奪取某些資源,或者簡單一點理解,佔有資源的程序不能再申請佔有其他資源,必須釋放手上的資源之後才能發起申請,這個其實也很難找到適用場景;

3. 程序在執行前申請得到所有的資源,否則該程序不能進入準備執行狀態。這個方法看似有點用處,但是它的缺點是可能導致資源利用率和程序併發性降低

4.  避免出現資源申請環路,即對資源事先分類編號,按號分配。這種方式可以有效提高資源的利用率和系統吞吐量,但是增加了系統開銷,增大了程序對資源的佔用時間。

(1). 最簡單、最常用的方法就是進行系統的重新啟動,不過這種方法代價很大,它意味著在這之前所有的程序已經完成的計算工作都將付之東流,包括參與死鎖的那些程序,以及未參與死鎖的程序;

(2). 撤消程序,剝奪資源。終止參與死鎖的程序,收回它們佔有的資源,從而解除死鎖。這時又分兩種情況:一次性撤消參與死鎖的全部程序,剝奪全部資源;或者逐步撤消參與死鎖的程序,逐步收回死鎖程序佔有的資源。一般來說,選擇逐步撤消的程序時要按照一定的原則進行,目的是撤消那些代價最小的程序,比如按程序的優先順序確定程序的代價;考慮程序執行時的代價和與此程序相關的外部作業的代價等因素;

(3). 程序回退策略,即讓參與死鎖的程序回退到沒有發生死鎖前某一點處,並由此點處繼續執行,以求再次執行時不再發生死鎖。雖然這是個較理想的辦法,但是操作起來系統開銷極大,要有堆疊這樣的機構記錄程序的每一步變化,以便今後的回退,有時這是無法做到的。

相關推薦

Java執行解決方案

要了解執行緒死鎖,首先要明白什麼是死鎖 死鎖 通俗點講:死鎖就是兩個或兩個以上的程序或執行緒在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。 用簡單一點的例子來說吧 比如這個交通堵塞的例子,從圖中可以看到四個方向行駛

執行解決辦法

死鎖是由於不同執行緒按照不同順序進行加鎖而造成的。如: 執行緒A:對lock a加鎖 => 對lock b加鎖 => dosth => 釋放lock b => 釋放lock a 執行緒B:對lock b加鎖 => 對lock a加鎖 

java執行例項

死鎖發生的四個必要條件:     1、互斥使用,即當資源被一個執行緒使用(佔有)時,別的執行緒不能使用     2、不可搶佔,資源請求者不能強制從資源佔有者手中奪取資源,資源只能由資源佔有者主動釋放。     3、請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資

執行以及解決方法

解決死鎖沒有簡單的方法,這是因為執行緒產生死鎖都各有各的原因,而且往往具有很高的負載。大多數軟體測試產生不了足夠多的負載,所以不可能暴露所有的執行緒錯誤。在這裡中,下面將討論開發過程常見的4類典型的死

java執行小結,解決應用掛的問題

JAVA多執行緒方面的知識,在此總結一下 1、在Java程式中,JVM負責執行緒的排程。執行緒排程是指按照特定的機制為多個執行緒分配CPU的使用權。 排程的模式有兩種:分時排程和搶佔式排程。分時排程是所有執行緒輪流獲得CPU使用權,並平均分配每個執行緒佔用CPU的時間;搶佔

一個多執行案例,如何避免解決問題?

多執行緒死鎖在java程式設計師筆試的時候時有遇見,死鎖概念在之前的文章有介紹,大家應該也都明白它的概念,不清楚的去翻看歷史文章吧。 下面是一個多執行緒死鎖的例子 輸出 thread1 get lock1 thread2 get lock2 兩個執行緒相互得到鎖1,鎖2,然後

工作執行操作主介面控制元件引起解決

問題描述: 在監控程式中,設計一監控迴圈。 標頭檔案 .h HANDLE                                          m_hEventExit; CWinThread*                              

Java執行-47-多執行

       本篇學習什麼是多執行緒死鎖,怎麼避免執行緒死鎖。這個問題,在面試了應該也經常被提到。關於,執行緒死鎖,有這麼一個故事。一個飯桌上,有豐盛的菜餚,圓桌圍著幾個哲學家,問題來了,每個哲學家只有一根筷子。假如必須得到兩根筷子,才

Java開發之執行同步造成的執行

案例解析: 兩個人面對面過獨木橋,甲和乙都已經在橋上走了一段距離,即佔用了橋的資源,甲如果想通過獨木橋的話,乙必須退出橋面讓出橋的資源,讓甲通過,但是乙不服,為什麼讓我先退出去,我還想先過去呢,於是就僵持不下,導致誰也過不了橋,這就是死鎖。 死鎖產生情況解析: 1.互斥條件(

java執行 和valitile關鍵字

死鎖 兩個或者多個執行緒都在等待對方釋放鎖,在寫多執行緒程式碼時要注意避免這種死鎖的發生 發生死鎖後可以在dos命令列輸入jps命令檢視java程序狀況 可以試用jstack -l 程序號   命令檢視當前類的問題 關閉jvm停止死鎖   以上節

Java筆記-多執行執行問題加簡單舉例

死鎖 導致死鎖的原因 Java中死鎖最簡單的情況是,一個執行緒T1持有鎖L1並且申請獲得鎖L2,而另一個執行緒T2持有鎖L2並且申請獲得鎖L1,因為預設的鎖申請操作都是阻塞的,所以執行緒T1和T2永遠被阻塞了。導致了死鎖。 這是最容易理解也是最簡單的死

嘗試解決在建構函式中同步呼叫Dns.GetHostAddressesAsync()引起的執行

(最終採用的是方法4) 看看在 Linux 與 Windows 上發生執行緒死鎖的後果。 Linux: Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -24 EMFILE too many o

VisualVM(9) 排查JAVA應用程式執行

Java虛擬機器效能管理神器 - VisualVM(9) 排查JAVA應用程式執行緒鎖 1. JAVA應用程式執行緒鎖原因 這個例子比較極端,一般情況下,出現鎖競爭激烈是比較常見的。 2. 排查JA

Java併發程式設計--執行安全問題與解決方案

本文簡介: 用多執行緒開發的人都知道,在多執行緒的開發過程中有可能會出現執行緒安全問題(專業術語叫記憶體可見性問題),但並不一定每次都會出現。出現這樣的情況,也會另開發者頭皮發麻,無從下手,接下來我們會慢慢深入,揭開多執行緒的神祕面紗。 本文主要介紹了Jav

Java模擬排查執行問題

一、模擬死鎖 public class App { public static void main( String[] args ) { Object object1 = new Object(); Object objec

java執行 哲學家就餐問題

    現在你理解了,一個物件可以有synchronized方法或其他形式的加鎖機制來防止別的任務在互斥還沒有釋放的時候就訪問這個物件。你已經學習過,任務可以變成阻塞狀態,所以就可能出現兩種情況:某個惹我怒在等待另一個任務,而後者又等待別的任務,這樣一直下去,直到這個鏈條上

Java 執行安全問題執行(讀書筆記)

多執行緒安全問題: 首先整理多執行緒同步的知識點,開頭肯定是要先探討探討多執行緒安全的問題。那麼嘛叫執行緒安全問題呢? 答: 我們知道Jvm虛擬機器的設計中執行緒的執行是搶佔式的,執行緒的執行時間是由底層系統決定的。所以就會有多個執行緒修改同一個資料時不同

java學習第十二天之多執行和併發

package MoreThreadLearn; /* 兩個儲戶到銀行存錢,每個人存了三次,一次100元 1、描述銀行 2、描述儲戶業務 分析多執行緒是否存在安全隱患? 1、執行緒任務中是否有共享的資料 2、是否多條操作共享資料的程式碼 */ public

java執行安全,執行執行通訊快速入門

一:多執行緒安全問題 ###1 引入 /* * 多執行緒併發訪問同一個資料資源 * 3個執行緒,對一個票資源,出售 */ public class ThreadDemo { public static void main(String[

什麼是執行,如何解決

產生死鎖的條件有四個: 互斥條件:所謂互斥就是程序在某一時間內獨佔資源。  請求與保持條件:一個程序因