1. 程式人生 > >多執行緒:死鎖,樂觀鎖,悲觀鎖

多執行緒:死鎖,樂觀鎖,悲觀鎖

死鎖:

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

本質原因:

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關鍵字就是悲觀鎖。併發訪問性不好。

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