文章目錄
- 鎖
-
- 1 死鎖
- 2 鎖的類型
-
- 2.1 樂觀鎖和悲觀鎖
- 2.2 公平鎖和非公平鎖
- 2.3 獨占鎖和共享鎖
- 2.4 讀寫鎖和排他鎖
- 2.5 可重入鎖
- 2.6 自旋鎖
- 3 鎖的等級
-
- 3.1 偏向鎖
- 3.2 輕量級鎖
- 3.3 重量級鎖
- 3.4 總結
鎖
1 死鎖
死鎖是指兩個或兩個以上的線程在執行任務過程中,因争奪資源而造成的互相等待的現象
産生死鎖的條件:
- 互斥條件:指線程對已經擷取的資源進行排他性使用,即該資源同時隻能由一個線程占用
- 請求并持有條件:指線程已經持有了至少一個資源,但又請求其他資源,如果請求不到則阻塞,但不釋放已有的資源
- 不可剝奪條件:指線程擷取到資源後,在使用完之前不能被其他線程占用
- 環路等待條件:指發生死鎖時,必然存在一個線程——資源的環形鍊
避免死鎖:破壞死鎖産生的條件
- 破壞請求并持有條件:一次性擷取所有所需的資源
- 破壞不可剝奪條件:占用資源的線程再擷取其他資源擷取不到時,釋放已有的資源
- 破壞環路等待條件:按某一順序申請資源,釋放資源則按相反的順序
2 鎖的類型
2.1 樂觀鎖和悲觀鎖
悲觀鎖:指對資料被外界的修改持悲觀态度,認為資料很容易被修改。是以操作前會先進行加鎖,操作結束再釋放鎖。悲觀鎖的實作往往依靠資料庫提供的鎖機制
樂觀鎖:與悲觀鎖相反。是以在通路資料時不會加鎖,隻有對資料送出更新的時候,才會檢測資料是否沖突。樂觀鎖通常通過version字段(CAS)或者使用業務狀态來實作
2.2 公平鎖和非公平鎖
公平鎖:線程擷取鎖的順序是按照線程請求鎖的順序
非公平鎖:通過搶占的方式來争奪鎖
2.3 獨占鎖和共享鎖
獨占鎖:一種悲觀鎖,保證任何時候僅有一個線程可以獲得鎖
共享鎖:一種樂觀鎖,允許多個線程同時進行讀操作
2.4 讀寫鎖和排他鎖
排他鎖:同一時刻隻允許一個線程通路
讀寫鎖:内部維護一個讀鎖一個寫鎖,通過分離讀鎖和寫鎖,在讀多寫少情況下提高性能
2.5 可重入鎖
當線程再次擷取一個自己已經擷取的鎖時,如果不會被阻塞,則該鎖是可重入鎖
原理:在鎖内部維護一個辨別,辨別哪個線程占用,一個計數器,計數該線程擷取鎖的次數
2.6 自旋鎖
當線程在擷取鎖時,如果發現鎖已經被占用,不會馬上阻塞自己,而是不放棄CPU使用權的情況下,多次嘗試擷取
3 鎖的等級
3.1 偏向鎖
偏向鎖在資源無競争情況下消除了同步語句,連CAS操作都不做了,提高程式的運作性能
一個線程在進入同步塊時,會檢查鎖的MarkWord裡是不是自己的線程ID
如果是,則表明該線程已經擷取偏向鎖,以後該線程進入和退出同步塊不需要花費CAS操作加鎖和解鎖
如果不是,則代表有另一個線程競争偏向鎖,嘗試用CAS來修改MarkWord中的線程ID。如果成功,表示另一個線程不存在了(釋放鎖了),如果失敗,則更新為輕量級鎖

3.2 輕量級鎖
線程嘗試用CAS修改MarkWord中的線程ID,如果失敗,則采用自旋來擷取鎖
如果自旋到一定程度,依然沒有擷取鎖,則更新為重量級鎖
3.3 重量級鎖
重量級鎖依賴于作業系統中的互斥量來實作
3.4 總結
偏向鎖
- 優點:加鎖和解鎖不需要額外的消耗
- 缺點:如果線程間存在鎖競争,則會帶來額外的鎖撤銷的消耗
- 适用:隻有一個線程通路同步塊
輕量級鎖
- 優點:競争的線程不會阻塞,提高了程式的響應速度
- 缺點:自旋會消耗CPU
- 适用:追求相應時間,同步塊執行速度非常快
重量級鎖
- 優點:不使用自旋,不會消耗CPU
- 缺點:線程阻塞,響應時間緩慢
- 适用:追求吞吐量,同步塊執行時間較長