鎖的概念:
首先我們先了解下什么是數據庫鎖,
鎖是事務對某個數據庫中的資源(如表和記 錄)存取前,先向系統提出請求,封鎖該資源,
事務獲得鎖后,即取得對數據的控制權,在事務釋放它的鎖之前,其他事務不能更新此數據。當事務撤消后,釋放被 鎖定的資源。
數據庫鎖的分類:
共享鎖:又叫S鎖或者讀鎖,加了共享鎖的數據對象可以被其他事務讀取,但不能修改, 通常是該數據對象被讀取完畢,鎖立即被釋放
排他鎖:又叫X鎖或者寫鎖,當數據對象被加上排它鎖時,一個事務必須得到鎖才能對該數據對象進行訪問,一直到事務結束鎖才被釋放。 在此之間其他的事 務不能對它讀取和修改。
死鎖:
死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。
這些永遠在互相等待的進程稱為死鎖進程
產生死鎖的必要條件:
1、互斥使用,即當資源被一個線程使用(占有)時,別的線程不能使用
2、不可搶占,資源請求者不能強制從資源占有者手中奪取資源,資源只能由資源占有者主動釋放。
3、請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資源的占有。
4、循環等待,即存在一個等待隊列:P1占有P2的資源,P2占有P3的資源,P3占有P1的資源。這樣就形成了一個等待環路。
死鎖產生的原因:
1) 系統資源的競爭
通常系統中擁有的不可剝奪資源,其數量不足以滿足多個進程運行的需要,使得進程在 運行過程中,會因爭奪資源而陷入僵局
2) 進程推進順序非法
進程在運行過程中,請求和釋放資源的順序不當,也同樣會導致死鎖。例如,並發進程 P1、P2分別保持了資源R1、R2,而進程P1申請資源R2,進程P2申請資源R1時,兩者都 會因為所需資源被占用而阻塞。
3)信號量使用不當也會造成死鎖。
進程間彼此相互等待對方發來的消息,結果也會使得這 些進程間無法繼續向前推進。
如何避免死鎖
三種用於避免死鎖的技術:
1)加鎖順序:
一個線程需要一些鎖,那么它必須按照確定的順序獲取鎖。它只有獲得了從順序上排在前面的鎖之后,才能獲取后面的鎖。
例如,線程2和線程3只有在獲取了鎖A之后才能嘗試獲取鎖C(獲取鎖A是獲取鎖C的必要條件)。因為線程1已經擁有了鎖A,
所以線程2和3需要一直等到鎖A被釋放。然后在它們嘗試對B或C加鎖之前,必須成功地對A加了鎖。
2)加鎖時限 :
另外一個可以避免死鎖的方法是在嘗試獲取鎖的時候加一個超時時間,這也就意味着在嘗試獲取鎖的過程中若超過了這個時限該線程則放棄對該鎖請求。
並會進行回退並釋放所有已經獲得的鎖,然后等待一段隨機的時間再重試。這段隨機的等待時間讓其它線程有機會嘗試獲取相同的這些鎖,
並且讓該應用在沒有獲得鎖的時候可以繼續運行(加鎖超時后可以先繼續運行干點其它事情,再回頭來重復之前加鎖的邏輯)。
3)死鎖檢測:
每當一個線程獲得了鎖,會在線程和鎖相關的數據結構中(map、graph等等)將其記下。除此之外,每當有線程請求鎖,也需要記錄在這個數據結構中。
當一個線程請求鎖失敗時,這個線程可以遍歷鎖的關系圖看看是否有死鎖發生。如果檢測到死鎖,就釋放所有鎖,回退,並且等待一段隨機的時間后再重試
遇到死鎖怎么辦
我們先了解下死鎖定理:
①如果資源分配圖中沒有環路,則系統沒有死鎖;
②如果資源分配圖中出現了環路,則系統可能有死鎖。
從上面的死鎖定理中我們可以知道只要打破死鎖的環路就可以解開死鎖,以下是處理死鎖的兩種名方法:
1)搶占資源:掛起某些死鎖進程,並搶占它的資源,將這些資源分配給其他的死鎖進程。但應防止被掛起的進程長時間得不到資源,而處於資源匱乏的狀態。
2)終止(或撤銷)進程:終止或撤銷系統中的一個或多個死鎖進程,直至打破死鎖狀態