JAVA是如何運行的五-synchronized

書接上回

當我們對一個代碼塊或者對象加synchronize關鍵字時,在早期的jdk版本中時直接申請系統鎖,然後將內存鎖住,這樣的結果就是大大降低執行效率。在JDK1.6版本後對synchronized的實現進行了各種優化,自旋鎖、偏向鎖和輕量級鎖

 

偏向鎖

  偏向鎖是Java 6之後加入的新鎖,它是一種針對加鎖操作的優化手段,經過研究發現,在大多數情況下,鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得,因此爲了減少同一線程獲取鎖(會涉及到一些CAS操作,耗時)的代價而引入偏向鎖。偏向鎖的核心思想是,如果一個線程獲得了鎖,那麼鎖就進入偏向模式,此時Mark Word 的結構也變爲偏向鎖結構,當這個線程再次請求鎖時,無需 再做任何同步操作,即獲取鎖的過程,這樣就省去了大量有關鎖申請的操作,從 而也就提供程序的性能。所以,對於沒有鎖競爭的場合,偏向鎖有很好的優化效 果,畢竟極有可能連續多次是同一個線程申請相同的鎖。但是對於鎖競爭比較激 烈的場合,偏向鎖就失效了,因爲這樣場合極有可能每次申請鎖的線程都是不相 同的,因此這種場合下不應該使用偏向鎖,否則會得不償失,需要注意的是,偏向鎖失敗後,並不會立即膨脹爲重量級鎖,而是先升級爲輕量級鎖。

輕量級鎖

  倘若偏向鎖失敗,虛擬機並不會立即升級爲重量級鎖,它還會嘗試使用一種 稱爲輕量級鎖的優化手段(1.6之後加入的),此時Mark Word 的結構也變爲輕量 級鎖的結構。輕量級鎖能夠提升程序性能的依據是“對絕大部分的鎖,在整個同 步週期內都不存在競爭”,注意這是經驗數據。需要了解的是,輕量級鎖所適應 的場景是線程交替執行同步塊的場合,如果存在同一時間訪問同一鎖的場合,就會導致輕量級鎖膨脹爲重量級鎖。這個時候也就是上面的Monitor.Enter和Monitor.Exit。鎖的升級過程是不可逆的。

自旋鎖

  虛擬機爲了避免線程真實地在操作系統層面掛起,會進行一項稱爲自旋鎖的優化手段。它是一個過渡,每一次升級之前先進行自旋,比如通過一定的自旋之後發現還是偏向鎖鎖的場景那麼就不進行鎖的升級。這是基於在大多數情況下,線程持有鎖的時間都不會太長,如果直接掛起操作系統層面的線程可能會得不償失,畢竟操作系統實 現線程之間的切換時需要從用戶態轉換到核心態,這個狀態之間的轉換需要相對 比較長的時間,時間成本相對較高,因此自旋鎖會假設在不久將來,當前的線程 可以獲得鎖,因此虛擬機會讓當前想要獲取鎖的線程做幾個空循環(這也是稱爲 自旋的原因),一般不會太久,可能是50個循環或100循環,在經過若干次循環後,如果得到鎖,就順利進入臨界區。如果還不能獲得鎖,那就會將線程在操作 系統層面掛起,這就是自旋鎖的優化方式,這種方式確實也是可以提升效率的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章