Java中的鎖系列2

經常聽到人家說什么偏向鎖、輕量級鎖、重量級鎖、自旋鎖,自適應自旋鎖。每當這個時候,以前的我是一臉懵逼…


那到底什么是偏向鎖、輕量級鎖、自旋鎖和重量級鎖?

首先我們需要明確一個概念,所有的這些鎖都是針對JVM的內容對象鎖。是synchronized實現里相關的東西。所以,要了解這些鎖,我們必須要知道synchronized在JVM里的實現原理。

JVM基于進入和退出Monitor對象來實現synchronized。在synchronized代碼塊開始位置織入monitorenter,在結束的位置(正常結束和異常結束處)織入monitorexit指令。線程執行到monitorenter處,會獲取鎖對象鎖對應的monitor的所有權,即嘗試獲得對象的鎖。(任意對象都有一個monitor與之關聯,當且一個monitor被持有后,他處于鎖定狀態)。

一、對象里存了什么東西

既然是對象鎖,那我肯定要知道對象是啥。

那java的對象結構到底是什么樣子的呢?我們看下Hotspot JVM中,32位機器下,對象的存儲內容。


這個圖一定要仔細看下。我們有時候也把第一個32位也叫MarkWord。

比如一個Integer對象,實際大小是:4(MarkWord)+4(對象地址)+4(實際int值)+4(補全的對齊)。所以,下次人家問一個Integer占多少字節的時候,勇敢的說出來:16個字節,int的4倍。


二、鎖的狀態和升級

從上面的圖中的MarkWord,我們可以知道一個對象有4種鎖的狀態,由低到高依次為:無鎖狀態。偏向鎖、輕量級鎖、重量級鎖,其實這些都是鎖的狀態。并且JVM還規定鎖的等級只可以升級,不可以降級。這種鎖升級卻不能降級的策略,目的是為了提高獲得鎖和釋放鎖的效率。


三、偏向鎖

首先為什么要有偏向鎖?

偏向鎖是為了在無鎖競爭的情況下,避免在輕量級鎖獲取過程中執行不必要的CAS原子指令,因為CAS原子指令雖然相對于重量級鎖來說開銷比較小但還是存在非常可觀的本地延遲。

那偏向鎖是怎么做到減少CAS的原子指令的呢?

我們來看下偏向鎖的獲取和釋放流程:

1、線程A獲得鎖,會在線程A的的棧幀里創建lock record(鎖記錄變量),則在鎖對象的對象頭里和lock record里存儲線程A的線程id.以后該線程的進入,就不需要CAS操作,只需要判斷是否是當前線程。

2、線程A獲取鎖后,不會主動釋放鎖。直到線程B也要競爭該鎖時,線程A才會釋放鎖。

偏向鎖的釋放,需要等待全局安全點(在這個時間點上沒有正在執行的字節碼),它會首先暫停擁有偏向鎖的線程,然后檢查持有偏向鎖的線程是否還活著,如果線程不處于活動狀態,則將對象頭設置成無鎖狀態。如果線程仍然活著,擁有偏向鎖的棧會被執行,遍歷偏向對象的所記錄。棧幀中的鎖記錄和對象頭的Mark Word要么重新偏向其他線程,要么恢復到無鎖,或者標記對象不適合作為偏向鎖。最后喚醒暫停的線程。

JVM怎么開啟/關閉偏向鎖?

偏向鎖在jdk1.6之后是默認開啟的。

通過jvm的參數-XX:-UseBiasedLocking,可以關閉偏向鎖,然后默認會進入輕量級鎖。

通過jvm的參數-XX:+UseBiasedLocking

-XX:BiasedLockingStartupDelay=0,可以開啟偏向鎖,并且設置偏向鎖的啟動延遲為0(這個值默認為5秒,因為jvm認為系統剛剛啟動的時候資源競爭是很激烈的。我們把這個值改為0,方便測試。)

我們可以來看一下,開啟和關閉偏向鎖之后,系統的差距


我們分別用兩個參數來運行這段代碼:

1、關閉偏向鎖。-XX:-UseBiasedLocking

運行結果如下:

2、開啟偏向鎖。-XX:+UseBiasedLocking-XX:BiasedLockingStartupDelay=0

通過這個結果,我們可以大概的得出結論:在本例子中,完全無鎖的情況下,開啟偏向鎖比關閉偏向鎖,性能提升了5%到10%。


四、輕量級鎖

輕量級鎖(Lightweight Locking)本意是為了減少多線程進入互斥的幾率,并不是要替代互斥。它利用CAS嘗試在進入互斥前,進行補救,避免調用操作系統層面的重量級互斥鎖。

線程A獲得鎖,會在線程A的棧幀里創建lock

record(鎖記錄變量),讓lock record的指針指向鎖對象的對象頭中的mark word.再讓mark word指向lock record.這就是獲取了鎖。

輕量級鎖,線程B在鎖競爭時,發現鎖已經被線程A占用,則線程B不進入內核態,讓線程B自旋(自旋的事情我們后面再講),執行空循環,等待線程A釋放鎖。如果,完成自旋策略還是發現線程A沒有釋放鎖,或者讓線程C占用了。則線程B試圖將輕量級鎖升級為重量級鎖。


五、重量級鎖

重量級鎖,就是讓爭搶鎖的線程從用戶態轉換成內核態,讓CPU借助操作系統進行線程協調。


六、自旋鎖

前面在講輕量級鎖的時候,我們已經提到了自旋。本質就是不讓出CPU,執行空循環,然后等待拿鎖。

使用自旋鎖后,線程被掛起的幾率相對減少,線程執行的連貫性相對加強。因此,對于那些鎖競爭不是很激烈,鎖占用時間很短的并發線程,具有一定的積極意義。但是,對于鎖競爭激烈,單線程鎖占用很長時間的并發程序,自旋鎖在自旋等待后,如果依然無法獲得對應的鎖,反而浪費了系統的資源。

我們來看下自己寫的一個自旋鎖。


在JDK1.6中,Java虛擬機提供-XX:+UseSpinning參數來開啟自旋鎖,使用-XX:PreBlockSpin參數來設置自旋鎖等待的次數,默認是10次。

在JDK1.7開始,自旋鎖的參數被取消,虛擬機不再支持由用戶配置自旋鎖,自旋鎖總是會執行,自旋鎖次數也由虛擬機自動調整,也就是開始使用自適應自旋鎖。

七、自適應自旋鎖

自適應意味著自旋的次數或者時間不再是固定的,而是由前一次在同一個鎖上的自旋時間以及鎖擁有者的狀態來決定。如果在同一個鎖對象上,自旋等待剛好成功獲得鎖, 并且在持有鎖的線程在運行中,那么虛擬機就會認為這次自旋也是很有可能獲得鎖, 進而它將允許自旋等待相對更長的時間。


總結:

這些東西可能在寫代碼的時候完全用不到,正常情況下,只需要寫個synchronized就完事了。但是,在虛擬機調優方面還是很有用的。當然,面試的時候也很有用。


參考資料:

http://www.cnblogs.com/shangxiaofei/p/5569879.html

http://www.cnblogs.com/javaminer/p/3889023.html

http://www.cnblogs.com/think-in-java/p/5520462.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容