java 偏向锁 怎么用_Java锁升级、偏向锁、轻量级锁
偏向鎖
當鎖對象第一次被線程獲取時,虛擬機會把對象頭的鎖狀態標志設置為01(即偏向狀態),同時,使用CAS操作把獲取到這個鎖的線程的ID記錄在對象頭的mark word中。如果這個CAS操作成功,那么,以后持有這個偏向鎖的線程在進入這個鎖相關的同步塊的時候都不需要進行同步,只需要測試對象頭的mark word中是否存儲著當前線程的ID。若測試成功,則直接進入同步塊。若測試失敗,則需要測試mark word中鎖狀態標志位是否為01。若不為01(即表示對象此時處于輕量級/重量級鎖狀態),則使用CAS操作競爭鎖。若為01(即01表示對象此時處于已偏向狀態),則嘗試使用CAS將對象頭的偏向線程ID改為當前線程ID。
此處,著重討論mark word中鎖狀態標志位為01的情況:由于偏向鎖采用了一種等到競爭出現才會釋放鎖的機制(即偏向鎖不會主動釋放),所以當前線程就會知道鎖對象此時(可能)處于競爭狀態了。(在全局安全點――沒有正在執行的字節碼)JVM會首先暫停持有偏向鎖的線程,然后檢查擁有偏向鎖的線程是否存活。若沒有存活,則將對象頭設置為無鎖狀態并重新偏向。若線程仍然存活,則持有偏向鎖的棧會被執行,遍歷偏向鎖的鎖記錄、棧中的鎖記錄以及對象頭的mark word(就是檢查持有偏向鎖的線程是否還需要持有偏向鎖)。若檢查結果表明該持有偏向鎖的線程不需要持有偏向鎖了,則將鎖對象恢復為無鎖狀態并重新偏向。否則表明此時鎖對象真的處于競爭狀態了,那么偏向鎖就會被升級成輕量級鎖。
注意:當鎖對象開啟偏向時mark word中有一個比特位將會被置為1,所以偏向狀態和未鎖定狀態除了其他字段的區別外,在這個比特位上也有區別。
輕量級鎖
在代碼進入同步塊的時候,如果此同步對象沒有被鎖定,即鎖標志位為01,那么JVM會先在當前線程的棧幀中創建一個存儲鎖對象頭中Mark Word拷貝的空間(稱為鎖記錄),同時將鎖對象頭中的Mark Word復制到鎖記錄中并加上Displaced前綴(Displaced Mark Word)。
然后,JVM使用CAS將鎖對象頭中的Mark Word更新為指向鎖記錄的指針。若更新成功,則當前線程便持有了該對象的鎖,并且鎖對象的標志位變為00(表示此對象處于輕量級鎖定狀態)。若更新操作失敗了,虛擬機會首先檢查對象的Mark Word是否指向當前線程的棧幀,如果是則表明當前線程已經擁有了這個對象的鎖,可以直接進入同步塊繼續執行。如果不是,則當前線程進入自旋,(個人見解,不當之處歡迎指正)則會有兩種情況會膨脹為重量級鎖: 當前線程自旋期間,有第三個線程來獲取鎖,則膨脹為重量級鎖,標志位被當前線程置為10,Mark Word中存儲的就是指向重量級鎖(互斥量)的指針,當前線程和第三個線程進入阻塞狀態;
當前線程自旋超過限定次數,則膨脹為重量級鎖,標志位被當前線程置為10,Mark Word中存儲的就是指向重量級鎖(互斥量)的指針,當前線程進入阻塞狀態。
如果當前線程自旋的時候沒有發生上面兩種情況,那么最終它將獲得鎖對象的輕量級鎖。
輕量級鎖的解鎖也是通過CAS操作進行的,如果對象的Mark Word仍指向線程的鎖記錄,那么就用CAS把對象當前的Mark Word和線程中的Displaced Mark Word替換回來。若替換成功,則整個同步過程完成,若替換失敗,則表明有其他線程競爭過鎖,就要在釋放鎖的同時喚醒被掛起的線程。
參考文獻:
1、《深入理解Java虛擬機》,周志明著;
2、《Java并發編程的藝術》,方騰飛,魏鵬,程曉明著;
總結
以上是生活随笔為你收集整理的java 偏向锁 怎么用_Java锁升级、偏向锁、轻量级锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端做后台管理系统有前途吗_关于后台管理
- 下一篇: html5 css3浏览器,五大主流浏览