同步和互斥的一些問題 死鎖,優先順序逆轉

2021-06-12 14:29:05 字數 4665 閱讀 1100

死鎖:死鎖指的是系統中併發執行的多個執行緒(程序)由於無法獲所需的資源而永久阻塞的狀態。

死鎖產生的必要條件:

排它性互斥:指的是資源在任意時刻只能由乙個任務(執行緒或程序)使用。如果此時還有其它任務請求該資源,則請求者只能等待,直至占有資源的任務釋放資源。

不可搶占:指的是當乙個任務擁有某種資源時,除非它主動釋放它,否則無法讓該任務失去該資源的擁有權。

持有和等待:指的是任務已經擁有了至少一種資源,然後又等待其它資源可用。

迴圈等待:指在發生死鎖時,必然存在乙個任務——資源的環形鏈,即任務集合中的p0正在等待乙個p1占用的資源;p1正在等待p2占用的資源,……,pn正在等待已被p0占用的資源。

產生死鎖時這4個必要條件都必須被滿足,因而處理死鎖就是要避免、預防這4個條件同時成立,或者在4個條件同時成立時破壞其中的任意乙個條件。處理死鎖的方法包括:

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

使用的限制條件一般有:

消除持有和等待這個條件:任務要一次申請完它所有需要的資源,只有當所有資源都可以獲得時它才能繼續執行。由於要求任務一次申請完其所有的所有資源,因而就不存在持有和等待這種情況。但是其不足在於:在實際的系統中很難**乙個任務需要那些資源,而且即便可以**出來任務所需的資源,任務在執行時也不一定就要用到這些資源,因為執行中真正需要的資源是由**路徑決定的,這就可能造成占有了不使用的資源從而導致出現浪費;更嚴重的問題在於,使用該防範隱含著乙個要求,即任務所需要的資源必須同時被釋放。這就意味著所有的資源都只能在任務已經不需要任何資源時才能被釋放,這會造成極大的資源浪費。

消除不可搶占這個條件:如果任務申請新的資源的請求不能被滿足,它就應該釋放它已經持有的資源。隨後任務再次嘗試申請資源的時候應該申請以前已經持有的資源和新需要的資源。與第一種條件相比,這種條件不需要任務一次申請其所需的所有資源,而是根據需要申請。但是該方法也存在嚴重的不足,因而它在申請一種資源失敗後,就會釋放所有已經持有的資源,當重新嘗試申請資源時就要申請這個時候所需的所有資源,這就需要追蹤所需的資源,而且在再次嘗試時,可能以前已經被持有過的資源也變的不可用了,這無疑加大了程式設計的複雜度。

消除迴圈等待這個條件: 該方法要求給資源進行統一編號,如果任務已經持有了編號為i的資源,則它只能申請編號大於i的資源。這就消除了迴圈等待這個條件。

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

避免死鎖演算法中最有代表性的演算法是dijkstra e.w 於2023年提出的銀行家演算法:

銀行家演算法是一種最有代表性的避免死鎖的演算法。在避免死鎖方法中允許任務動態地申請資源,但系統在進行資源分配之前,應先計算此次分配資源的安全性,若分配不會導致系統進入不安全狀態,則分配,否則等待。

安全序列是指乙個任務序列是安全的,即對於每乙個任務pi(1≤i≤n),它之後的任務所需要的資源量不超過系統當前剩餘資源量與所有程序pj (j < i )當前占有資源量之和。

安全狀態和不安全狀態:

為了使用該策略,每個任務都需要預估它所需要的最大資源量,然後系統使用該資訊建立乙個資源需求表以供使用。但是通常這種預估都是比較困難的。而且由於預估的是最大資源量,而實際執行中乙個任務並不一定會真正用到完它所預估的最大資源量,因而使用這種預估進行死鎖避免時有可能導致不必要的阻塞。

死鎖檢測並不須事先採取任何限制性措施,它只用於在執行過程中發生死鎖。並精確地確定與死鎖有關的任務和資源,然後就可以採取適當措施,從系統中將已發生的死鎖清除掉。

所謂單例項資源即該資源只有1個,因此也只能被乙個任務所申請使用。

畫出進行死鎖檢測時系統資源的使用、申請有向圖graph。其中如果任務當前擁有某個資源,就畫一條從該資源到該任務的有向邊;如果任務正在申請某個資源,就畫一條從該任務到該資源的有向邊。

從該圖中取出乙個未遍歷過的節點,將圖graph中的該節點標記為已遍歷,並建立乙個空列表l用來容納圖graph的節點。

檢查該節點是否已經存在於列表l中了,如果是,則就存在死鎖;否則將該節點加入列表l的尾部

檢查圖graph中是否還存在未檢查的從該節點發出的有向邊,如果沒有,則跳轉到步驟6

從這些有向邊中選取一條,在圖graph中將該有向邊標記為已檢查,將該有向邊的入節點當作當前節點,在圖graph中將當前節點標記為已遍歷,並跳轉到步驟3

如果l非空,則將l中最後乙個節點從l中刪除,如果l還非空,則將l中最後乙個節點設為當前節點,並跳轉到步驟4

如果圖graph中還有未遍歷過的節點,則跳轉到步驟2;否則演算法結束,不存在死鎖

所謂多例項資源即該資源有多個,因此在同一時間可能被多個任務所使用

列出進行死鎖檢測時每種資源的剩餘量和每個任務需要使用的量

找出乙個任務,它所需要的每種資源量小於或等於系統此時剩餘的相應資源的量,即它的申請要求可以被滿足;如果找不到這樣的任務,則系統存在死鎖

標記步驟2找出的任務為可執行,並將此時它所持有的資源量加到系統剩餘資源量上

如果系統中還存在沒有標記為可執行的任務,就回到步驟2;否則演算法結束,系統不存在死鎖

它一般與檢測死鎖一起使用。常用的實施方法是撤銷或掛起一些任務,以便**一些資源,再將這些資源分配給已處於阻塞狀態的任務,使之轉為就緒狀態,以繼續執行。死鎖的檢測和解除措施,有可能使系統獲得較好的資源利用率和吞吐量,但在實現上難度也最大。

這些策略一般都是由系統實現和支援的,在應用程式的編寫中也有一些原則可供參考:

不要在可能會對效能造成不良影響的長時間操作(如 i/o)中持有鎖。

不要在呼叫模組外且可能重進入模組的函式時持有鎖。

一般情況下,優先使用粗粒度鎖,如果確定粗粒度鎖對效能造成了很大影響,再使用細粒度鎖。

使用多個鎖時,盡量讓所有任務都按照相同的順序來上鎖以避免死鎖。

優先順序逆**優先順序逆轉指的是在可搶占系統中,高優先順序任務由於等待低優先順序任務所持有的資源而阻塞,同時低優先順序優先執行的狀態。它的基本表現有兩種情形:

低優先順序t1任務持有資源r執行;高優先順序任務t2啟動開始執行,高優先順序任務需要使用資源r,但是無法獲得該資源,因而阻塞;低優先順序任務t1繼續執行,看上去好像高優先順序任務被低優先順序任務搶占了

低優先順序t1任務持有資源r執行;高優先順序任務t2啟動開始執行,高優先順序任務需要使用資源r,但是無法獲得該資源,因而阻塞;低優先順序任務t1被排程執行;此時乙個優先順序小於t2但是大於t1的任務t3啟動了,它就會搶占任務t1;最終看起來好像任務t3搶占了高優先順序任務t2,如果說情形1由於競爭資源還比較容易看出來的話,情形2則更具有迷惑性,t2和t3之間不存在競爭關係,t3竟然在t1之前執行了。

大部分情況下優先順序逆轉並不導致問題,因為高優先順序任務只是延遲執行了,但是有時候這也會是個問題。

由於優先順序逆轉和資源的共享使用有關,因而可以通過對資源新增訪問控制協議來解決這個問題,可以通過如下三種資源訪問控制協議來解決優先順序逆轉問題:

優先順序繼承協議

天花板優先順序協議

優先順序天花板協議

該協議的訪問控制規則:如果乙個任務t1由於無法獲取資源r而阻塞,並且其優先順序高於資源r的持有者t2的優先順序,就提公升其持有者t2的優先順序到任務t1的優先順序。具體的規則:

在天花板優先順序中,所有任務所需要的所有資源都是已知的,所有任務的優先順序也是已知的。每種資源都有乙個天花板優先順序,它等於所有需要使用該資源的任務的最高優先順序。

比如系統中有任務t1(優先順序4)、t2(優先順序6)、t3(優先順序8)、t4(優先順序10),資源r1、r2、r3、r4,其中任務t1需要使用資源r1、r3,任務t2需要使用資源r2,任務t3需要使用資源r2、r4,任務t4需要使用資源r1、r3、r4.

則資源r1、r2、r3、r4的天花板優先順序分別為:10,8,10,10

使用該協議時的規則為:

類似於天花板優先順序協議,在優先順序天花板協議中所有任務所需要的所有資源都是已知的,所有任務的優先順序也是已知的。每種資源都有乙個天花板優先順序,它等於所有需要使用該資源的任務的最高優先順序。

比如系統中有任務t1(優先順序4)、t2(優先順序6)、t3(優先順序8)、t4(優先順序10),資源r1、r2、r3、r4,其中任務t1需要使用資源r1、r3,任務t2需要使用資源r2,任務t3需要使用資源r2、r4,任務t4需要使用資源r1、r3、r4.

則資源r1、r2、r3、r4的天花板優先順序分別為:10,8,10,10

二者不同之處在於規則,在優先順序天花板協議中有乙個當前優先順序天花板,當前優先順序天花板等於當前正被使用的所有資源的最高天花板優先順序,基於當前優先順序天花板,該協議的規則為:

該協議結合了優先順序繼承協議和天花板優先順序協議,用當前正在被使用的資源的優先順序天花板計算出了乙個當前天花板優先順序,但是它又不同於執行任務的優先順序;任務的執行優先順序只有在任務阻塞了乙個高優先順序任務時才會改變,而且這個改變不是簡單的設定為當前優先順序變化板,而是繼承它所阻塞的高優先順序任務的優先順序

經常見到的乙個需求是使得應用程式只有乙個執行例項在執行。這可以通過記錄鎖來實現,實現方法是:

在啟動應用後建立乙個特殊檔案,該檔案的位置和名字是特定唯一的

嘗試在該檔案上上乙個記錄鎖寫鎖,並鎖住整個檔案

如果上鎖失敗,說明有乙個應用例項在執行,退出

繼續執行

之所以記錄鎖可以實現該目的是因為:根據記錄鎖的特性,無論記錄鎖的持有者程序以何種方式結束,系統都會自動釋放它所持有的所有記錄鎖--如果程序沒有自己釋放它的話。因而只要無法鎖定就肯定表明有乙個正在執行的例項正在持有這把鎖。

由於命名訊號量也具有類似的特性(系統會在程序終止時自動關閉其開啟的所有命名訊號量),因而命名訊號量也可以用於該目的。

一些收藏 運算子的優先順序

今天看到幾個題目比較有意思 分享一下。真的沒有看出來自己 錯了 但是乙個沒答對 今天正好群裡有人在問一道php運算子優先順序的問題,正好以前也遇到過類似的問題,這裡整理一下吧,方便大家理解 以防掉坑 先來道簡單的 a 3 if a 5 var dump a int 6 所以乙個好的編碼習慣 對於數字...

關於 , 和 的優先順序問題

下面 輸出什麼?a 3 b 5 if a 5 b 7 echo a.b a.16 b.68 c.35 d.以上都不對 怎麼說呢,這是一道比較坑的題目,應該用等於,用了賦值,這個是很容易就會被發現,然後至少我是直接去下步運算,先 再輸出,結果為68.問題當然不能這麼簡單了,這個答案是錯的,正確的答案是...

執行緒的優先順序及執行緒的同步問題

一.可以使用setpriority方法來設定 執行緒測優先順序 有可能影響執行緒的執行順序 1 min priority 10 max priority 5 max priority 預設 優先順序高的可能先被使用 如結果所示,每次c都會先執行,但只是有可能影響 public class threa...