久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

synchronized底層實現(xiàn)原理及鎖優(yōu)化

 __安如少年 2020-12-07

一、概述
1,、synchronized作用

  • 原子性:synchronized保證語句塊內操作是原子的

  • 可見性:synchronized保證可見性(通過“在執(zhí)行unlock之前,,必須先把此變量同步回主內存”實現(xiàn))

  • 有序性:synchronized保證有序性(通過“一個變量在同一時刻只允許一條線程對其進行l(wèi)ock操作”)

2、synchronized的使用

  • 修飾實例方法,,對當前實例對象加鎖

  • 修飾靜態(tài)方法,,多當前類的Class對象加鎖

  • 修飾代碼塊,對synchronized括號內的對象加鎖

二,、實現(xiàn)原理

1,、jvm基于進入和退出Monitor對象來實現(xiàn)方法同步和代碼塊同步。

方法級的同步是隱式,,即無需通過字節(jié)碼指令來控制的,,它實現(xiàn)在方法調用和返回操作之中。JVM可以從方法常量池中的方法表結構(method_info Structure) 中的 ACC_SYNCHRONIZED 訪問標志區(qū)分一個方法是否同步方法,。當方法調用時,,調用指令將會 檢查方法的 ACC_SYNCHRONIZED 訪問標志是否被設置,如果設置了,,執(zhí)行線程將先持有monitor(虛擬機規(guī)范中用的是管程一詞),, 然后再執(zhí)行方法,最后再方法完成(無論是正常完成還是非正常完成)時釋放monitor,。

代碼塊的同步是利用monitorenter和monitorexit這兩個字節(jié)碼指令,。它們分別位于同步代碼塊的開始和結束位置。當jvm執(zhí)行到monitorenter指令時,,當前線程試圖獲取monitor對象的所有權,,如果未加鎖或者已經(jīng)被當前線程所持有,就把鎖的計數(shù)器+1,;當執(zhí)行monitorexit指令時,,鎖計數(shù)器-1;當鎖計數(shù)器為0時,,該鎖就被釋放了,。如果獲取monitor對象失敗,該線程則會進入阻塞狀態(tài),,直到其他線程釋放鎖,。

這里要注意:

  • synchronized是可重入的,所以不會自己把,自己鎖死

  • synchronized鎖一旦被一個線程持有,,其他試圖獲取該鎖的線程將被阻塞,。

關于ACC_SYNCHRONIZED 、monitorenter,、monitorexit指令,,可以看一下下面的反編譯代碼:

public class SynchronizedDemo {
    public synchronized void f(){    //這個是同步方法
        System.out.println("Hello world");
    }
    public void g(){
        synchronized (this){//這個是同步代碼塊
            System.out.println("Hello world");
        }
    }
    public static void main(String[] args) {

    }
}

使用javap -verbose SynchronizedDemo反編譯后得到
在這里插入圖片描述
在這里插入圖片描述
我們看到對于同步方法,反編譯后得到ACC_SYNCHRONIZED 標志,,對于同步代碼塊反編譯后得到monitorenter和monitorexit指令,。

三、理解Java對象頭

在JVM中,,對象在內存中的布局分為三塊區(qū)域:對象頭,、實例數(shù)據(jù)和對齊填充。
在這里插入圖片描述
實例變量:存放類的屬性數(shù)據(jù)信息,,包括父類的屬性信息,,如果是數(shù)組的實例部分還包括數(shù)組的長度,這部分內存按4字節(jié)對齊,。

填充數(shù)據(jù):由于虛擬機要求對象起始地址必須是8字節(jié)的整數(shù)倍,。填充數(shù)據(jù)不是必須存在的,僅僅是為了字節(jié)對齊,。

HotSpot虛擬機的對象頭分為兩部分信息,,第一部分用于存儲對象自身運行時數(shù)據(jù),如哈希碼,、GC分代年齡等,,這部分數(shù)據(jù)的長度在32位和64位的虛擬機中分別為32位和64位。官方稱為Mark Word,。另一部分用于存儲指向對象類型數(shù)據(jù)的指針,,如果是數(shù)組對象的話,還會有一個額外的部分存儲數(shù)組長度,。

虛擬機位數(shù)對象頭結構描述
32位/64位Mark Word存儲對象的哈希碼,、GC分代年齡、鎖信息等
32位/64位Class MetaData Address指向對象類型數(shù)據(jù)的指針
32位/64位數(shù)組長度如果是數(shù)組對象的話,,有這一部分,,否則沒有

由于對象頭的信息是與對象自身定義的數(shù)據(jù)沒有關系的額外存儲成本,,因此考慮到JVM的空間效率,,Mark Word 被設計成為一個非固定的數(shù)據(jù)結構,以便存儲更多有效的數(shù)據(jù),,它會根據(jù)對象本身的狀態(tài)復用自己的存儲空間,。

在這里插入圖片描述

四、JVM對synchronized的鎖優(yōu)化

Synchronized是通過對象內部的一個叫做監(jiān)視器鎖(monitor)來實現(xiàn)的,監(jiān)視器鎖本質又是依賴于底層的操作系統(tǒng)的Mutex Lock(互斥鎖)來實現(xiàn)的,。而操作系統(tǒng)實現(xiàn)線程之間的切換需要從用戶態(tài)轉換到核心態(tài),,這個成本非常高,狀態(tài)之間的轉換需要相對比較長的時間,,這就是為什么Synchronized效率低的原因,。因此,這種依賴于操作系統(tǒng)Mutex Lock所實現(xiàn)的鎖我們稱之為“重量級鎖”,。

Java SE 1.6為了減少獲得鎖和釋放鎖帶來的性能消耗,,引入了“偏向鎖”和“輕量級鎖”:鎖一共有4種狀態(tài),級別從低到高依次是:無鎖狀態(tài),、偏向鎖狀態(tài),、輕量級鎖狀態(tài)和重量級鎖狀態(tài)。鎖可以升級但不能降級,。

1,、偏向鎖
偏向鎖是JDK1.6中引用的優(yōu)化,它的目的是消除數(shù)據(jù)在無競爭情況下的同步原語,,進一步提高程序的性能,。

偏向鎖的獲取:

  1. 判斷是否為可偏向狀態(tài)

  2. 如果為可偏向狀態(tài),,則判斷線程ID是否是當前線程,,如果是進入同步塊;

  3. 如果線程ID并未指向當前線程,,利用CAS操作競爭鎖,,如果競爭成功,將Mark Word中線程ID更新為當前線程ID,,進入同步塊

  4. 如果競爭失敗,,等待全局安全點,準備撤銷偏向鎖,,根據(jù)線程是否處于活動狀態(tài),,決定是轉換為無鎖狀態(tài)還是升級為輕量級鎖。

當鎖對象第一次被線程獲取的時候,,虛擬機會把對象頭中的標志位設置為“01”,,即偏向模式。同時使用CAS操作把獲取到這個鎖的線程ID記錄在對象的Mark Word中,,如果CAS操作成功,。持有偏向鎖的線程以后每次進入這個鎖相關的同步塊時,虛擬機都可以不再進行任何同步操作,。

偏向鎖的釋放:
偏向鎖使用了遇到競爭才釋放鎖的機制,。偏向鎖的撤銷需要等待全局安全點,然后它會首先暫停擁有偏向鎖的線程,然后判斷線程是否還活著,,如果線程還活著,,則升級為輕量級鎖,否則,,將鎖設置為無鎖狀態(tài),。

在這里插入圖片描述

2、輕量級鎖
輕量級鎖也是在JDK1.6中引入的新型鎖機制,。它不是用來替換重量級鎖的,,它的本意是在沒有多線程競爭的情況下,減少傳統(tǒng)的重量級鎖使用操作系統(tǒng)互斥量產生的性能消耗,。

加鎖過程:
在代碼進入同步塊的時候,,如果此對象沒有被鎖定(鎖標志位為“01”狀態(tài)),虛擬機首先在當前線程的棧幀中建立一個名為鎖記錄(Lock Record)的空間,,用于存儲對象目前Mark Word的拷貝(官方把這份拷貝加了一個Displaced前綴,,即Displaced Mark Word)。然后虛擬機使用CAS操作嘗試將對象的Mark Word更新為指向鎖記錄(Lock Record)的指針,。如果更新成功,,那么這個線程就擁有了該對象的鎖,并且對象的Mark Word標志位轉變?yōu)椤?0”,,即表示此對象處于輕量級鎖定狀態(tài),;如果更新失敗,虛擬機首先會檢查對象的Mark Word是否指向當前線程的棧幀,,如果說明當前線程已經(jīng)擁有了這個對象的鎖,,那就可以直接進入同步塊中執(zhí)行,否則說明這個鎖對象已經(jīng)被其他線程占有了,。如果有兩條以上的線程競爭同一個鎖,,那輕量級鎖不再有效,要膨脹為重量級鎖,,鎖標志變?yōu)椤?0”,,Mark Word中存儲的就是指向重量級鎖的指針,而后面等待的線程也要進入阻塞狀態(tài),。

在這里插入圖片描述
在這里插入圖片描述
解鎖過程:
如果對象的Mark Word仍然指向線程的鎖記錄,,那就用CAS操作將對象當前的Mark Word與線程棧幀中的Displaced Mark Word交換回來,如果替換成功,,整個同步過程就完成了,。如果替換失敗,說明有其他線程嘗試過獲取該鎖,,那就要在釋放鎖的同時,,喚醒被掛起的線程,。

如果沒有競爭,,輕量級鎖使用CAS操作避免了使用互斥量的開銷,,但如果存在競爭,除了互斥量的開銷外,,還額外發(fā)生了CAS操作,,因此在有競爭的情況下,輕量級鎖比傳統(tǒng)重量級鎖開銷更大,。

3,、重量級鎖
Synchronized的重量級鎖是通過對象內部的一個叫做監(jiān)視器鎖(monitor)來實現(xiàn)的,監(jiān)視器鎖本質又是依賴于底層的操作系統(tǒng)的Mutex Lock(互斥鎖)來實現(xiàn)的,。而操作系統(tǒng)實現(xiàn)線程之間的切換需要從用戶態(tài)轉換到核心態(tài),,這個成本非常高,狀態(tài)之間的轉換需要相對比較長的時間,,這就是為什么Synchronized效率低的原因,。

4、自旋鎖
互斥同步對性能影響最大的是阻塞的實現(xiàn),,掛起線程和恢復線程的操作都需要轉入到內核態(tài)中完成,,這些操作給系統(tǒng)的并發(fā)性能帶來很大的壓力。
于是在阻塞之前,,我們讓線程執(zhí)行一個忙循環(huán)(自旋),,看看持有鎖的線程是否釋放鎖,如果很快釋放鎖,,則沒有必要進行阻塞,。

5、鎖消除
鎖消除是指虛擬機即時編譯器(JIT)在運行時,,對一些代碼上要求同步,,但是檢測到不可能發(fā)生數(shù)據(jù)競爭的鎖進行消除。

6,、鎖粗化
如果虛擬機檢測到有這樣一串零碎的操作都對同一個對象加鎖,,將會把加鎖同步的范圍擴展(粗化)到整個操作序列的外部。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多