【synchronized底層原理之3】JDK1.6對鎖所作的優化

參考網頁

https://www.cnblogs.com/dsj2016/p/5714921.htmlhtml

https://www.zhihu.com/question/55075763程序員

JDK1.6對synchronized鎖所作的優化

優化包括自旋鎖、鎖粗化、鎖消除(鎖清除)、輕量級鎖和偏向鎖。安全

這些都是Java虛擬機層面的優化,對Java程序員是無感知的(Java程序員在程序層面是看不出什麼的,可是JVM內部已對synchronized作了優化)。要說有感知的話,就是synchronized在多線程下的性能提升了(JDK1.6相比於JDK1.5),這些都得益於JVM層面鎖的優化,就是上面所說的自旋鎖、鎖粗化、鎖清除、偏向鎖和輕量級鎖。多線程

自旋鎖:本質上就是CPU空轉等待一下子獲取鎖的控制權,而不是立刻進入阻塞狀態

原理--互斥同步->產生阻塞->上下文切換->操做系統級別用戶態和核心態的切換,而使用自旋不會產生阻塞,是個有益的補充

一般狀況下,共享數據的鎖定狀態只持續很短的一段時間,爲了這很短的一段時間進行上下文切換並不值得。性能

原理--CPU空轉等待獲取鎖的控制權

自旋就是不停循環看是否能等到上個線程本身釋放鎖。這個問題是基於一個現實考量的:不少拿了鎖的線程會很快釋放鎖。由於通常敏感的操做不會不少。固然這個是一個不能徹底肯定的狀況,只能說整體上是一種優化優化

舉個例子就比如一我的要上廁所發現廁所裏面有人,他能夠:1,等一小會。2,跑去另外的地方上廁所。等一小會不必定能等到前一我的出來,不過若是跑去別的廁所的花費的時間確定比等一小會結果前一我的出來了長。固然等完告終果那我的沒出來仍是要跑去別的地方上廁所這是最慢的。spa

優勢--高效:不會引發上下文切換

缺點--自旋時間若是過長就會形成CPU資源的浪費

自適應自旋--根據以往經驗設置合理的自旋次數、設計合理的自旋時間

自適應自旋能夠根據以往自旋等待時間的經驗,計算出一個較爲合理的本次自旋等待時間。操作系統

好比第一次設置最多自旋10次,結果在自旋的過程當中成功得到了鎖,那麼下一次就能夠設置成最多自旋20次。道理是:一個鎖若是可以在自旋的過程當中被釋放說明頗有可能下一次也會發生這種事。那麼就更要給這個鎖某種「便利」方便其不阻塞得鎖(畢竟快了不少)。一樣若是屢次嘗試的結果是徹底不能自旋等到其釋放鎖,那麼就說明頗有可能這個臨界區裏面的操做比較耗時間。就減少自旋的次數,由於其可能性過小了。線程

鎖粗化--JVM擴大加鎖的範圍

如有一系列操做,反覆地對同一把鎖進行上鎖和解鎖操做,編譯器會擴大這部分代碼的同步塊的邊界,從而只使用一次上鎖和解鎖操做。設計

試想有一個循環,循環裏面是一些敏感操做,有的人就在循環裏面寫上了synchronized關鍵字。這樣確實沒錯不過效率也許會很低,由於其頻繁地拿鎖釋放鎖。要知道鎖的取得(假如只考慮重量級MutexLock)是須要操做系統調用的,從用戶態進入內核態,開銷很大。因而針對這種狀況也許虛擬機發現了以後會適當擴大加鎖的範圍(因此叫鎖粗化)以免頻繁的拿鎖釋放鎖的過程。

鎖消除(鎖清除)--JVM去掉多餘的鎖

編譯器會清除一些使用了同步,但同步塊中沒有涉及共享數據的鎖,從而減小多餘的同步。

經過逃逸分析發現其實根本就沒有別的線程產生競爭的可能(別的線程沒有臨界量的引用),而「自做多情」地給本身加上了鎖。有可能虛擬機會直接去掉這個鎖。

輕量級鎖:(相對於重量級鎖)取消互斥同步,使用CAS操做同步

本質

使用CAS取代互斥同步

與重量級鎖的比較

重量級鎖是一種悲觀鎖,使用互斥同步來保證線程的安全;

輕量級鎖是一種樂觀鎖,使用CAS操做進行同步。

實現原理

當線程請求鎖時,若該鎖對象的Mark Word中標誌位爲01(未鎖定狀態),則在該線程的棧幀中建立一塊名爲『鎖記錄』的空間,而後將鎖對象的Mark Word拷貝至該空間;而後經過CAS操做將鎖對象的Mark Word指向該鎖記錄;

若CAS操做成功,則輕量級鎖的上鎖過程成功;

若CAS操做失敗,再判斷當前線程是否已經持有了該輕量級鎖;若已經持有,則直接進入同步塊;若還沒有持有,則表示該鎖已經被其餘線程佔用,此時輕量級鎖就要膨脹成重量級鎖。

適用場景

輕量級鎖比重量級鎖性能更高的前提是,在輕量級鎖被佔用的整個同步週期內,不存在其餘線程的競爭。若在該過程當中一旦有其餘線程競爭,那麼就會膨脹成重量級鎖,從而除了使用互斥量之外,還額外發生了CAS操做,此時耗時更長,會更慢。

偏向鎖:(相對於輕量級鎖)徹底取消同步操做

做用

偏向鎖是爲了消除無競爭狀況下的同步原語,進一步提高程序性能。

與輕量級鎖的區別

輕量級鎖是在無競爭的狀況下使用CAS操做來代替互斥量的使用,從而實現同步;而偏向鎖是在無競爭的狀況下徹底取消同步。

與輕量級鎖的相同點

它們都是樂觀鎖,都認爲同步期間不會有其餘線程競爭鎖。

原理

當線程請求到鎖對象後,將鎖對象的狀態標誌位改成01,即偏向模式。而後使用CAS操做將線程的ID記錄在鎖對象的Mark Word中。之後該線程能夠直接進入同步塊,連CAS操做都不須要。可是,一旦有第二條線程須要競爭鎖,那麼偏向模式當即結束,進入輕量級鎖的狀態。

優勢

偏向鎖能夠提升有同步但沒有競爭的程序性能。可是若是鎖對象時常被多條線程競爭,那偏向鎖就是多餘的。

偏向鎖能夠經過虛擬機的參數來控制它是否開啓

相關文章
相關標籤/搜索