談談大廠愛問的Synchronized原理(建議收藏)

ITPUB社群發表於2023-03-09

最近小夥伴大廠面試歸來,很多都被問到了Synchronized,很多同學對原理都忘了,下面我就再談談Synchronized的原理。

一般都會涉及到如下內容:內容底層實現,鎖升級、怎麼儲存等等,下面一一詳解@mikechen

談談大廠愛問的Synchronized原理(建議收藏)

Synchronized

synchronized關鍵字解決的是多個執行緒之間訪問資源的同步性,synchronized 翻譯為中文的意思是同步,也稱之為”同步鎖“。

synchronized的作用是保證在同一時刻, 被修飾的程式碼塊或方法只會有一個執行緒執行,以達到保證併發安全的效果。

Synchronized的使用方式

談談大廠愛問的Synchronized原理(建議收藏)

主要有3種使用方式:

1.修飾例項方法:作用於當前例項加鎖

public synchronized void method(){        // 程式碼}

2.修飾靜態方法:作用於當前類物件加鎖

public static synchronized void method(){         // 程式碼  }

3.修飾程式碼塊:指定加鎖物件,對給定物件加鎖

synchronized(this){   //程式碼                                    }

 

Synchronized的底層實現

synchronized的底層實現是完全依賴JVM虛擬機器的,所以談synchronized的底層實現,就不得不談資料在JVM記憶體的儲存:Java物件頭,以及Monitor物件監視器。

1.Java物件頭

在JVM虛擬機器中,物件在記憶體中的儲存佈局,可以分為三個區域:

  • 物件頭(Header)

  • 例項資料(Instance Data)

  • 對齊填充(Padding)

Java物件頭主要包括兩部分資料:

談談大廠愛問的Synchronized原理(建議收藏)

1)型別指標(Klass Pointer)

是物件指向它的類後設資料的指標,虛擬機器透過這個指標來確定這個物件是哪個類的例項;

2)標記欄位(Mark Word)

用於儲存物件自身的執行時資料,如雜湊碼(HashCode)、GC分代年齡、鎖狀態標誌、執行緒持有的鎖、偏向執行緒 ID、偏向時間戳等等,它是實現輕量級鎖和偏向鎖的關鍵.

所以,很明顯synchronized使用的鎖物件是儲存在Java物件頭裡的標記欄位裡。

2.Monitor

monitor描述為物件監視器,可以類比為一個特殊的房間,這個房間中有一些被保護的資料,monitor保證每次只能有一個執行緒能進入這個房間進行訪問被保護的資料,進入房間即為持有monitor,退出房間即為釋放monitor

談談大廠愛問的Synchronized原理(建議收藏)

上圖是syncrhoized同步程式碼塊反編譯截圖,可以很清楚的看見,主要就是透過鎖物件的monitor的取用(monitorenter)與釋放來(monitorexit)實現的。

3.執行緒狀態流轉在Monitor上體現

當多個執行緒同時請求某個物件監視器時,物件監視器會設定幾種狀態用來區分請求的執行緒:

  • Contention List:所有請求鎖的執行緒將被首先放置到該競爭佇列

  • Entry List:Contention List中那些有資格成為候選人的執行緒被移到Entry List

  • Wait Set:那些呼叫wait方法被阻塞的執行緒被放置到Wait Set

  • OnDeck:任何時刻最多隻能有一個執行緒正在競爭鎖,該執行緒稱為OnDeck

  • Owner:獲得鎖的執行緒稱為Owner

  • !Owner:釋放鎖的執行緒

下圖反映了個狀態轉換關係:

談談大廠愛問的Synchronized原理(建議收藏)

Synchronized 的鎖升級

鎖解決了資料的安全性,但是同樣帶來了效能的下降,hotspot 虛擬機器的作者經過調查發現,大部分情況下,加鎖的程式碼不僅僅不存在多執行緒競爭,而且總是由同一個執行緒多次獲得。

所以基於這樣一個機率,synchronized 在JDK1.6 之後做了一些最佳化,為了減少獲得鎖和釋放鎖來的效能開銷,引入了偏向鎖,鎖的狀態根據競爭激烈的程度從低到高不斷升級。

談談大廠愛問的Synchronized原理(建議收藏)

1.無鎖

無鎖沒有對資源進行鎖定,所有的執行緒都能訪問並修改同一個資源,但同時只有一個執行緒能修改成功。

2.偏向鎖

偏向鎖是JDK6中引入的一項鎖最佳化,大多數情況下,鎖不僅不存在多執行緒競爭,而且總是由同一執行緒多次獲得,為了讓執行緒獲得鎖的代價更低而引入了偏向鎖。

偏向鎖是指一段同步程式碼一直被一個執行緒所訪問,那麼該執行緒會自動獲取鎖,降低獲取鎖的代價。

3.輕量級鎖

是指當鎖是偏向鎖的時候,被另外的執行緒所訪問,偏向鎖就會升級為輕量級鎖,其他執行緒會透過自旋的形式嘗試獲取鎖,不會阻塞,從而提高效能。

4.重量級鎖

指的是原始的Synchronized的實現,重量級鎖的特點:其他執行緒試圖獲取鎖時,都會被阻塞,只有持有鎖的執行緒釋放鎖之後才會喚醒這些執行緒。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2938830/,如需轉載,請註明出處,否則將追究法律責任。

相關文章