synchronized

java 底層提供的一種同步機(jī)制(關(guān)鍵字)

可重入(偏向鎖時(shí) 當(dāng)前線(xiàn)程可重入)
異常會(huì)釋放鎖,如果不想被釋放,可以catch異常

鎖信息只能存儲(chǔ)在對(duì)象(實(shí)例)上

使用對(duì)象做鎖,一定要加final,對(duì)象的屬性發(fā)生變化不影響鎖的使用,但是定義發(fā)生改變會(huì)導(dǎo)致原來(lái)的鎖失效 例如重新 o = new Object();

//鎖信息存儲(chǔ)在調(diào)用t1方法的實(shí)例上
public synchronized void t1(){}

public  void t2(){
    //鎖信息存儲(chǔ)在當(dāng)前實(shí)例上
    synchronized(this){ }

    final Object o = new Object();
    //鎖信息存儲(chǔ)在實(shí)例o上
    synchronized(o){}
    
    //鎖信息存儲(chǔ)在實(shí)例Object的對(duì)象上,俗稱(chēng)類(lèi)鎖,
    //jvm 加載Object類(lèi)時(shí),會(huì)自動(dòng)劃分一塊內(nèi)存,生成Object類(lèi)的對(duì)象
    synchronized(Object.class){}
}

//鎖信息存儲(chǔ)在t3方法所處類(lèi)的對(duì)象上,俗稱(chēng)類(lèi)鎖
public synchronized static void t3(){}

實(shí)現(xiàn)過(guò)程

  1. java代碼: 加 synchronize
  2. 字節(jié)碼層級(jí): monitorenter moniterexit
  3. 執(zhí)行過(guò)程: 自動(dòng)升級(jí)鎖
  4. 匯編層級(jí): lock comxchg

鎖升級(jí)

參考

  1. 無(wú)鎖: 新new對(duì)象
  2. 偏向鎖: 第一次拿鎖時(shí)上的是偏向鎖,鎖信息為當(dāng)前線(xiàn)程id號(hào),當(dāng)前線(xiàn)程可重入
  3. 輕量級(jí)鎖: 發(fā)送任意競(jìng)爭(zhēng),撤銷(xiāo)偏向鎖,上輕量級(jí)鎖,使用自旋的方式(CAS)競(jìng)爭(zhēng)鎖.
  4. 重量級(jí)鎖:jdk1.6以下:自旋超過(guò)10次,cpu等待核數(shù)>1/2,1.6之后加入自適應(yīng)自旋,jvm自己控制,自動(dòng)升級(jí)(向操作系統(tǒng)申請(qǐng)).

ps:
輕量級(jí)鎖在自旋拿鎖,不停的循環(huán),特別消耗cpu,每個(gè)重量級(jí)鎖都擁有一個(gè)隊(duì)列,等待執(zhí)行的線(xiàn)程會(huì)進(jìn)入wait狀態(tài),不消耗cpu
用戶(hù)態(tài): 應(yīng)用程序可以使用的資源
內(nèi)核態(tài): 使用硬件資源必須通過(guò)內(nèi)核執(zhí)行,比如拿鎖,向顯卡寫(xiě)入數(shù)據(jù)等

鎖降級(jí)

重量級(jí)鎖的降級(jí)發(fā)生于STW(執(zhí)行垃圾收集算法)階段,降級(jí)對(duì)象就是那些僅僅能被VMThread訪(fǎng)問(wèn)而沒(méi)有其他JavaThread訪(fǎng)問(wèn)的對(duì)象。因此沒(méi)有什么意義,可以認(rèn)為沒(méi)有鎖降級(jí)

鎖消除

當(dāng)jvm發(fā)現(xiàn)某有鎖對(duì)象的引用只能被單一線(xiàn)程使用時(shí)(局部變量,棧私有),會(huì)自動(dòng)消除對(duì)象內(nèi)部的鎖,例如以下情況就無(wú)鎖

public void add (String str1,String str2){
    StringBuffer sb = new StringBuffer();
    //會(huì)自動(dòng)消除append方法上的鎖
    sb.append(str1).appand(str2);  
}

鎖粗化

當(dāng)jvm發(fā)現(xiàn)一連串的操作都對(duì)同一對(duì)象加鎖,jvm就會(huì)將加鎖的范圍粗化到這一連串操作的外部(如while),使得一連串操作只需要加一次鎖

private static StringBuffer sb = new StringBuffer();
public static void test (String str){
    sb.clear();
    while(i<100){ //會(huì)自動(dòng)消粗化到while虛幻體外部
        sb.append(str);  
         i++;
    }
    
}

synchronized vs CAS

  1. 在高爭(zhēng)用 高耗電的環(huán)境下 synchronize 效率更高
  2. 在低爭(zhēng)用 低耗電的環(huán)境下 CAS效率更高
  3. synchronized 到重量級(jí)之后 進(jìn)入隊(duì)列 (不消耗CPU)
  4. CAS 等待期間消耗CPU
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容