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