Synchronized是通過(guò)對(duì)象內(nèi)部的一個(gè)叫做監(jiān)視器鎖(monitor)來(lái)實(shí)現(xiàn)的。但是監(jiān)視器鎖本質(zhì)又是依賴于底層的操作系統(tǒng)的Mutex Lock來(lái)實(shí)現(xiàn)的。而操作系統(tǒng)實(shí)現(xiàn)線程之間的切換這就需要從用戶態(tài)轉(zhuǎn)換到核心態(tài),這個(gè)成本非常高,狀態(tài)之間的轉(zhuǎn)換需要相對(duì)比較長(zhǎng)的時(shí)間,這就是為什么Synchronized效率低的原因。因此,這種依賴于操作系統(tǒng)Mutex Lock所實(shí)現(xiàn)的鎖我們稱(chēng)之為“重量級(jí)鎖”。JDK中對(duì)Synchronized做的種種優(yōu)化,其核心都是為了減少這種重量級(jí)鎖的使用。JDK1.6以后,為了減少獲得鎖和釋放鎖所帶來(lái)的性能消耗,提高性能,引入了“輕量級(jí)鎖”和“偏向鎖”。
無(wú)鎖,偏向鎖,輕量鎖,重量鎖
隨著鎖的競(jìng)爭(zhēng),鎖可以從偏向鎖升級(jí)到輕量級(jí)鎖,
再升級(jí)的重量級(jí)鎖(但是鎖的升級(jí)是單向的,也就是說(shuō)只能從低到高升級(jí),不會(huì)出現(xiàn)鎖的降級(jí))。
JDK 1.6中默認(rèn)是開(kāi)啟偏向鎖和輕量級(jí)鎖的
volatile
而volatile關(guān)鍵字就是Java中提供的另一種解決可見(jiàn)性和有序性問(wèn)題的方案。對(duì)于原子性,需要強(qiáng)調(diào)一點(diǎn),也是大家容易誤解的一點(diǎn):對(duì)volatile變量的單次讀/寫(xiě)操作可以保證原子性的,如long和double類(lèi)型變量,但是并不能保證i++這種操作的原子性,因?yàn)楸举|(zhì)上i++是讀、寫(xiě)兩次操作
并發(fā)環(huán)境下的單例實(shí)現(xiàn)方式,我們通??梢圆捎秒p重檢查加鎖(DCL)的方式來(lái)實(shí)現(xiàn)。
public class Singleton {
public static volatile Singleton singleton;
/**
* 構(gòu)造函數(shù)私有,禁止外部實(shí)例化
*/
private Singleton() {};
public static Singleton getInstance() {
if (singleton == null) {
synchronized (singleton) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}