Java中synchronized同步块的执行流程
必要知識
Java 對象的數據結構
- 在 HotSpot 虛擬機中,Java 對象在內存中存儲的布局可以分為 3 塊區域:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)
- 對象頭中的 Mark Word 部分,用于存儲對象自身的運行時數據,如哈希碼(HashCode)、GC 分代年齡、鎖狀態標志、線程持有的鎖、偏向線程 ID、偏向時間戳等,其中的最后 2bit 是鎖狀態標志位(無鎖、偏向鎖、輕量級鎖、重量級鎖、GC 標識)
鎖升級流程
無鎖 -> 偏向鎖 -> 輕量級鎖 -> 重量級鎖
無鎖: 沒有對資源進行鎖定,所有的線程都能訪問并修改同一個資源,但同時只有一個線程能修改成功,其他修改失敗的線程會不斷重試直到修改成功。
偏向鎖:對象的代碼一直被同一線程執行,不存在多個線程競爭,該線程在后續的執行中自動獲取鎖,降低獲取鎖帶來的性能開銷。偏向鎖,指的就是偏向第一個加鎖線程,該線程是不會主動釋放偏向鎖的,只有當其他線程嘗試競爭偏向鎖才會被釋放。
偏向鎖的撤銷,需要在某個時間點上沒有字節碼正在執行時,先暫停擁有偏向鎖的線程,然后判斷鎖對象是否處于被鎖定狀態。如果線程不處于活動狀態,則將對象頭設置成無鎖狀態,并撤銷偏向鎖;
如果線程處于活動狀態,升級為輕量級鎖的狀態。
輕量級鎖(樂觀鎖):輕量級鎖是指當鎖是偏向鎖的時候,被第二個線程 B 所訪問,此時偏向鎖就會升級為輕量級鎖,線程 B 會通過自旋的形式嘗試獲取鎖,線程不會阻塞,從而提高性能。
當前只有一個等待線程,則該線程將通過自旋進行等待。但是當自旋超過一定的次數時,輕量級鎖便會升級為重量級鎖;當一個線程已持有鎖,另一個線程在自旋,而此時又有第三個線程來訪時,輕量級鎖也會升級為重量級鎖。
重量級鎖(悲觀鎖):指當有一個線程獲取鎖之后,其余所有等待獲取該鎖的線程都會處于阻塞狀態。
重量級鎖通過對象內部的監視器(monitor)實現,而其中 monitor 的本質是依賴于底層操作系統的 Mutex Lock 實現,操作系統實現線程之間的切換需要從用戶態切換到內核態,切換成本非常高。
synchronized 的執行過程
在所有的鎖都啟用的情況下,線程進入臨界區時會先去獲取偏向鎖,如果已經存在偏向鎖了,則會嘗試獲取輕量級鎖,啟用自旋鎖,如果自旋也沒有獲取到鎖,則使用重量級鎖,沒有獲取到鎖的線程阻塞掛起,直到持有鎖的線程執行完同步塊喚醒他們
總結
以上是生活随笔為你收集整理的Java中synchronized同步块的执行流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 画蛇添足的寓意是什么 画蛇添足的故事告诉
- 下一篇: java美元兑换,(Java实现) 美元