標籤:文章 原因 區別 也有 效能 cursor color 簡單 over
死結兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。為什麼會產生死結:① 因為系統資源不足。② 進程運行推進的順序不合適。 ③ 資源分派不當。產生死結的條件有四個:① 互斥條件:所謂互斥就是進程在某一時間內獨佔資源。② 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。③ 不剝奪條件:進程已獲得資源,在末使用完之前,不能強行剝奪。④ 迴圈等待條件:若干進程之間形成一種頭尾相接的迴圈等待資源關係。避免死結:避免嵌套封鎖:這是死結最主要的原因的,如果你已經有一個資源了就要避免封鎖另一個資源。如果你運行時只有一個對象封鎖,那是幾乎不可能出現一個死結局面的。只對有請求的進行封鎖:你應當只想你要啟動並執行資源擷取封鎖,比如在上述程式中我在封鎖的完全的對象資源。但是如果我們只對它所屬領域中的一個感興趣,那我們應當封鎖住那個特殊的領域而並非完全的對象。避免無限期的等待:如果兩個線程正在等待對象結束,無限期的使用線程加入,如果你的線程必須要等待另一個線程的結束,若是等待進程的結束加入最好準備最長時間。
饑餓一個或者多個線程因為種種原因無法獲得所需要的資源,導致一直無法執行的狀態。解決饑餓的方案被稱之為“公平性” – 即所有線程均能公平地獲得運行機會。Java中導致饑餓的原因:① 高優先順序線程吞噬所有的低優先順序線程的CPU時間。② 線程被永久堵塞在一個等待進入同步塊的狀態,因為其他線程總是能在它之前持續地對該同步塊進行訪問。③ 線程在等待一個本身也處於永久等待完成的對象(比如調用這個對象的wait方法),因為其他線程總是被持續地獲得喚醒。在Java中實現公平性方案,需要:① 使用鎖,而不是同步塊。② 公平鎖。③ 注意效能方面。詳細學習文章饑餓和公平:http://ifeve.com/starvation-and-fairness/#header活鎖任務或者執行者沒有被阻塞,由於某些條件沒有滿足,導致一直重複嘗試,失敗,嘗試,失敗。
| 活鎖和死結的區別在於,處於活鎖的實體是在不斷的改變狀態,所謂的“活”, 而處於死結的實體表現為等待;活鎖有可能自行解開,死結則不能。 |
活鎖的例子:單一實體的活鎖例如線程從隊列中拿出一個任務來執行,如果任務執行失敗,那麼將任務重新排入佇列,繼續執行。假設任務總是執行失敗,或者某種依賴的條件總是不滿足,那麼線程一直在繁忙卻沒有任何結果。協同導致的活鎖生活中的典型例子: 兩個人在窄路相遇,同時向一個方向避讓,然後又向另一個方向避讓,如此反覆。通訊中也有類似的例子,多個使用者共用通道(最簡單的例子是大家都用對講機),同一時刻只能有一方發送資訊。發送訊號的使用者會進行衝突檢測, 如果發生衝突,就選擇避讓,然後再發送。 假設避讓演算法不合理,就導致每次發送,都衝突,避讓後再發送,還是衝突。電腦中的例子:兩個線程發生了某些條件的碰撞後重新執行,那麼如果再次嘗試後依然發生了碰撞,長此下去就有可能發生活鎖。活鎖的解決方案:解決協同活鎖的一種方案是調整重試機制。比如引入一些隨機性。例如如果檢測到衝突,那麼就暫停隨機的一定時間進行重試。這回大大減少碰撞的可能性。 典型的例子是乙太網路的CSMA/CD檢測機制。另外為了避免可能的死結,適當加入一定的重試次數也是有效解決辦法。儘管這在業務上會引起一些複雜的邏輯處理。比如約定重試機制避免再次衝突。 例如自動駕駛的防碰撞系統(假想的例子),可以根據序號約定檢測到相撞風險時,序號小的飛機朝上飛, 序號大的飛機朝下飛。 |
轉:java高並發學習記錄-死結,活鎖,饑餓