1. 程式人生 > >多執行緒死鎖以及解決方法

多執行緒死鎖以及解決方法

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

(1)資料庫死鎖 

  在資料庫中,如果一個連線佔用了另一個連線所需的資料庫鎖,則它可以阻塞另一個連線。如果兩個或兩個以上的連線相互阻

塞,則它們都不能繼續執行,這種情況稱為數據庫死鎖。資料庫死鎖問題不易處理,通常資料行進行更新時,需要鎖定該資料行,

執行更新,然後在提交或回滾封閉事務時釋放鎖。由於資料庫平臺、配置的隔離級以及查詢提示的不同,獲取的鎖可能是細粒度或

粗粒度的,它會阻塞(或不阻塞)其他對同一資料行、表或資料庫的查詢。基於資料庫模式,

讀寫操作會要求遍歷或更新多個索

引、驗證約束、執行觸發器等。每個要求都會引入更多鎖。此外,其他應用程式還可能正在訪問同一資料庫模式中的某些物件,

獲取不同應用程式所具有的鎖。所有這些因素綜合在一起,資料庫死鎖幾乎不可能被消除了。值得慶幸的是,資料庫死鎖通常是可

恢復的:當資料庫發現死鎖時,它會強制銷燬一個連線(通常是使用最少的連線),並回滾其事務。這將釋放所有與已經結束的事

務相關聯的鎖,至少允許其他連線中有一個可以獲取它們正在被阻塞的鎖。

由於資料庫具有這種典型的死鎖處理行為,所以當出現數據庫死鎖問題時,資料庫常常只能重試整個事務。當資料庫連線被銷

毀時,會丟擲可被應用程式捕獲的異常,並標識為資料庫死鎖。如果允許死鎖異常傳播到初始化該事務的程式碼層之外,則該程式碼層

可以啟動一個新事務並重做先前所有工作。當出現問題就重試,由於資料庫可以自由地獲取鎖,所以幾乎不可能保證兩個或兩個以

上的執行緒不發生資料庫死鎖。此方法至少能保證在出現某些資料庫死鎖情況時,應用程式能正常執行。

(2)資源池耗盡死鎖

  客戶端的增加導致資源池耗盡死鎖是由於負載而造成的,即資源池太小,而每個執行緒需要的資源超過了池中的可用資源。假設

連線池最多有10個連線,同時有10個對外部併發呼叫。這些執行緒中每一個都需要一個數據庫連線用來清空池。現在,每個執行緒都執

行巢狀的呼叫。則所有執行緒都不能繼續,但又都不放棄自己的第一個數據庫連線。這樣,10個執行緒都將被死鎖。

  研究此類死鎖,會發現執行緒儲存中有大量等待獲取資源的執行緒,以及同等數量的空閒且未阻塞的活動資料庫連線。當應用程式

死鎖時,如果可以在執行時檢測連線池,就能確認連線池實際上已空。

  修復此類死鎖的方法包括:增加連線池的大小或者重構程式碼,以便單個執行緒不需要同時使用很多資料庫連線。或者可以設定內

部呼叫使用不同的連線池,即使外部呼叫的連線池為空,內部呼叫也能使用自己的連線池繼續。

(3)單執行緒、多衝突資料庫連線死鎖

  對同一執行緒執行巢狀的呼叫有時出現死鎖,此情形即使在非高負載系統中通常也會發生。當第一個(外部)連線已獲取第二個

(內部)連線所需要的資料庫鎖,則第二個連線將永久阻塞第一個連線,並等待第一個連線被提交或回滾,這就出現了死鎖情形。

因為資料庫沒有注意到兩個連線之間的關係,所以資料庫不會將此情形檢測為死鎖。這樣即使不存在併發,此程式碼也將導致死鎖。

此情形有多種具體的變種,可以涉及多個執行緒和兩個以上的資料庫連線。

(4)Java虛擬機器鎖與資料庫鎖衝突

  這種情形發生在資料庫鎖與Java虛擬機器鎖並存的時候。在這種情況下,一個執行緒佔有一個數據庫鎖並嘗試獲取Java虛擬機器鎖。

同時,另一個執行緒佔有Java虛擬機鎖並嘗試獲取資料庫鎖。此時,資料庫發現一個連線阻塞了另一個連線,但由於無法阻止連線繼

續,所以不會檢測到死鎖。Java虛擬機發現同步的鎖中有一個執行緒,並有另一個嘗試進入的執行緒,所以即使Java虛擬機器能檢測到死

鎖並對它們進行處理,它還是不會檢測到這種情況。

  總而言之,JAVA應用程式中的死鎖是一個大問題——它能導致整個應用程式慢慢終止,還很難被分離和修復,尤其是當開發人員

不熟悉如何分析死鎖環境的時候。

(5). 死鎖的經驗法則  

    (1) 對大多數的Java程式設計師來說最簡單的防止死鎖的方法是對競爭的資源引入序號,如果一個執行緒需要幾個資源,那麼它必須先得到

小序號的資源,再申請大序號的資源。可以在Java程式碼中增加同步關鍵字的使用,這樣可以減少死鎖,但這樣做也會影響效能。如果

負載過重,資料庫內部也有可能發生死鎖。

    (2)瞭解資料庫鎖的發生行為。假定任何資料庫訪問都有可能陷入資料庫死鎖狀況,但是都能正確進行重試。例如瞭解如何從應用

伺服器獲取完整的執行緒轉儲以及從資料庫獲取資料庫連線列表(包括互相阻塞的連線),知道每個資料庫連線與哪個Java執行緒相關

聯。瞭解Java執行緒和資料庫連線之間對映的最簡單方法是向連線池訪問模式新增日誌記錄功能。

    (3)當進行巢狀的呼叫時,瞭解哪些呼叫使用了與其它呼叫同樣的資料庫連線。即使巢狀呼叫執行在同一個全域性事務中,它仍將使

用不同的資料庫連線,而不會導致巢狀死鎖。

    (4)確保在峰值併發時有足夠大的資源池。

    (5)避免執行資料庫呼叫或在佔有Java虛擬機器鎖時,執行其他與Java虛擬機器無關的操作。 
  

    最重要的是,多執行緒設計雖然是困難的,但在開始程式設計之前詳細設計系統能夠幫助你避免難以發現死鎖的問題。死鎖在語言層面

上不能解決,就需要一個良好設計來避免死鎖。

相關推薦

執行以及解決方法

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

執行解決辦法

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

Python | 執行問題的巧妙解決方法

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是Python專題的第25篇文章,我們一起來聊聊多執行緒開發當中死鎖的問題。 死鎖 死鎖的原理非常簡單,用一句話就可以描述完。就是當多執行緒訪問多個鎖的時候,不同的鎖被不同的執行緒持有,它們都在等待其他執行緒釋放出鎖來,於是便

執行的產生以及如何避免

一、死鎖的定義 多執行緒以及多程序改善了系統資源的利用率並提高了系統 的處理能力。然而,併發執行也帶來了新的問題——死鎖。所謂死鎖是指多個執行緒因競爭資源而造成的一種僵局(互相等待),若無外力作用,這些程序都將無法向前推進。 下面我們通過一些例項來說明死鎖現象。 先看生活中

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

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

34-執行--+執行間通訊+等待喚醒機制+生產者消費者問題

一、死鎖 1、死鎖的常見情形之一:同步的巢狀 說明:同步的巢狀,至少得有兩個鎖,且第一個鎖中有第二個鎖,第二個鎖中有第一個鎖。eg:同步程式碼塊中有同步函式,同步函式中有同步程式碼塊。下面的例子,同步程式碼塊的鎖是obj,同步函式的鎖是this。t1執行緒先執行同步程式碼塊,獲取鎖obj,需

Java執行-47-執行

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

java 執行 和valitile關鍵字

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

python中的程序,執行,,協程

本人根據自己的理解來總結的,如果有錯誤的地方還請各位大佬指正,謝謝了. 程序:程式是計算機可執行的二進位制資料,只有被作業系統呼叫的時候才開始它們的生命週期.程序就是程式的一次執行,擁有自己的地址空間,記憶體,程序id(pid),資料棧及其他記錄其執行軌跡的輔助資料;最小的

執行程式碼

public class DeadLock { //建立兩個物件,一個執行緒持有鎖A並且申請獲得鎖B,而另一個執行緒持有鎖B並且申請獲得鎖A就會發生死鎖。 private static final Object A=new Object(); priv

java 執行 哲學家就餐問題

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

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

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

執行經典案例,必定會發生死

        Java執行緒死鎖是一個經典的多執行緒問題,因為不同的執行緒都在等待根本不可能被釋放的鎖,從而導致所有的任務都無法繼續完成。換言之只要互相等待對方釋放鎖就有可能出現死鎖。下面將用一個簡單的例子加以說明,如有問題,請多多指教。        某日AB兩位壯士各獲

Java執行解決方案

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

ios執行解析

問題:ios 誰能分析下多執行緒死鎖問題,感謝,分析圖一二為什麼是這個結果? (問題帖子連結:http://zhidao.baidu.com/link?url=Lr9sNchrdnCLJdoc73WeHfL3lcu7lBvyKQ2hBrF2jbyM3wkJWeK0

java執行,執行以及Condition類的使用

看了網上非常多的執行程式碼,很多都是重複的再說一件事,可能對於java老鳥來說,理解java的多執行緒是非常容易的事情,但是對於我這樣的菜鳥來說,這個實在有點難,可能是我太菜了,網上重複的陳述對於我理解這個問題一點幫助都沒有.所以這裡我寫下我對於這個問題的理解,目的是為了防止我忘記. 還是從程式碼例項開始講起

Python執行以及執行帶來的資料錯亂和解決方法

摘至本人有道雲筆記《Python執行緒》 1.python多執行緒的建立 在Python中,同樣可以實現多執行緒,有兩個標準模組thread和threading,不過我們主要使用更高階的threading模組 threading模組提供的類:      Thread,

java 執行synchronized同步方法,同步程式碼塊

執行緒安全問題 同步和非同步 我們知道多個執行緒共享堆記憶體,當兩個或者多個執行緒呼叫同一個物件的方法操作物件成員時,因為cpu輪流執行執行緒,執行緒A剛開始操作物件方法,修改了資料,輪到執行緒B執行,執行緒B也操作物件方法,修改資料,可能又輪到執行緒A操作物件方法,接著上次執行緒A的剩餘部

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