互斥同步之鎖機制
互斥同步是保證線程安全的一種手段逞壁,在Java中提供了兩種鎖機制來實現(xiàn)
- 同步鎖synchronized
- Reentrant鎖
鎖機制雖然能有效地保證線程安全流济,但是其也存在問題:當線程因為請求鎖進入阻塞或者等待被喚醒時,會給降低系統(tǒng)的性能腌闯。這是由于Java的線程實現(xiàn)是跟操作系統(tǒng)的線程綁定的,如果需要阻塞或者喚醒一個線程時雕憔,就需要用戶態(tài)和內(nèi)核態(tài)之間來回切換姿骏,應用在操作系統(tǒng)上的這種狀態(tài)切換是很耗費CPU時間的,所以有可能對于非常簡單的同步代碼塊斤彼,系統(tǒng)用于狀態(tài)切換的時間要比執(zhí)行同步代碼的時間要長分瘦。所以鎖機制的優(yōu)化的目標就是盡可能降低線程進入阻塞/等待喚醒的概率,相關(guān)的技術(shù)有:
- 偏向鎖
- 輕量鎖
- 傳統(tǒng)鎖
- 同步鎖和Reentrant鎖的比較
比較項 | 同步鎖 | Reetrant鎖 |
---|---|---|
是否可重入 | 是 | 是 |
是否等待可中斷 | 否 | 是 |
是否公平鎖 | 否 | 是 |
是否可鎖定多個條件 | 鎖定一個 | 鎖定多個 |
- 鎖的狀態(tài)轉(zhuǎn)換
鎖的狀態(tài)轉(zhuǎn)化.jpg
偏向鎖和輕量級鎖帶來的優(yōu)化的前提是假設(shè)多線程在鎖對象的同步周期內(nèi)都不存在競爭嘲玫;
在Java中鎖的狀態(tài)切換順序為偏向鎖-->輕量級鎖-->重量級鎖(傳統(tǒng)鎖)
當程序中雖然寫了同步的代碼,但是實際上每次只有一個線程在請求鎖并扇,鎖對象處于偏向鎖去团;
當出現(xiàn)另外一個線程再請求鎖時,鎖對象就由偏向鎖轉(zhuǎn)為輕量鎖穷蛹。
如果每次都是一個線程獲取鎖土陪,執(zhí)行完同步代碼塊,釋放鎖后才有另一個線程來請求鎖肴熏,則鎖對象會一直處于輕量鎖鬼雀;
如果在某一時刻出現(xiàn)至少兩個線程同時請求一把鎖時,鎖對象就由輕量鎖升級為重量級鎖蛙吏。
詳細的實現(xiàn)機制請參考:
http://luojinping.com/2015/07/09/java%E9%94%81%E4%BC%98%E5%8C%96/