多線程:死鎖,樂觀鎖,悲觀鎖

死鎖:

兩個或者多個進程競爭統一資源而形成的僵持的局面,若無外力作用,將無法推進。

本質原因:

1)系統資源有限

2)進程推進順序不合理

死鎖的條件:

(1)互斥。某個資源在一段時間只能有一個進程佔有,只有當使用該資源的進程釋放後,其他進程才能佔有該資源。

(2)請求和保持。進程A已經擁有了一些資源,現在要訪問其他資源,A進程阻塞,但是在A等待的過程中,不會釋放已有的資源,

(3)不剝奪。不可搶佔條件,進程在未使用完資源之前,不能被其他進程搶佔,只能由該進程的佔有者自行釋放。

(4)環路等待。存在一個等待序列{P1,P2,P3...Pn},其中,P1等待P2所佔有的資源,P2等待P3所佔有的某種資源,Pn等待P1佔有的某種資源。

上述4個條件只要有1個不滿足,死鎖就會排除。

解決死鎖的方法:

死鎖的預防,避免,檢測與恢復

預防:確保系統永遠不會進入死鎖狀態。打破4個條件中的一個或者幾個

避免:在使用前進行判斷,只允許不會產生死鎖的進程申請資源。安全序列,銀行家算法,加鎖順序

檢測與解除:檢測到運行系統進入死鎖,進行恢復。允許系統進入死鎖狀態。

樂觀鎖:

假設不會發生併發衝突。只在提交時是否違反數據完整性。不能解決髒讀的問題。適用於併發量非常大的情況。

每次拿數據的時候都認爲別人不會修改,所以不會上鎖,但是在更新的時候會判斷在此期間別人有沒有更新這個數據,可以使用版本號等機制。適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫提供的類似於write_condition機制。java.util.concurrent.atomic包下的原子變量類就是使用樂觀鎖的一種實現CAS實現的。

hibernate樂觀鎖的實現:

基於version,版本號

基於timestamp,時間戳

悲觀鎖:

假定會發生併發衝突,屏蔽一切可能違反數據完整性的操作。

每次去拿數據的時候都認爲別人會修改,所以每次拿數據的時候都會上鎖,這樣別人想拿這個數據時就會阻塞直到它拿到鎖。傳統的關係型數據庫就用到了很多這種鎖機制,比如行鎖,表鎖,讀鎖,寫鎖等,都是在操作之前先上鎖。java裏面的synchronized關鍵字就是悲觀鎖。併發訪問性不好。

併發量不大,不允許髒讀的情況下使用悲觀鎖

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章