鎖的級別從低到高:
無鎖 -> 偏向鎖 -> 輕量級鎖 -> 重量級鎖
鎖分級別原因:
沒有優化以前,sychronized是重量級鎖(悲觀鎖),使用 wait 和 notify、notifyAll 來切換線程狀態非常消耗系統資源;線程的掛起和喚醒間隔很短暫,這樣很浪費資源,影響性能。所以 JVM 對 sychronized 關鍵字進行了優化,把鎖分為 無鎖、偏向鎖、輕量級鎖、重量級鎖 狀態。
無鎖:沒有對資源進行鎖定,所有的線程都能訪問並修改同一個資源,但同時只有一個線程能修改成功,其他修改失敗的線程會不斷重試直到修改成功。
偏向鎖:對象的代碼一直被同一線程執行,不存在多個線程競爭,該線程在后續的執行中自動獲取鎖,降低獲取鎖帶來的性能開銷。偏向鎖,指的就是偏向第一個加鎖線程,該線程是不會主動釋放偏向鎖的,只有當其他線程嘗試競爭偏向鎖才會被釋放。
偏向鎖的撤銷,需要在某個時間點上沒有字節碼正在執行時,先暫停擁有偏向鎖的線程,然后判斷鎖對象是否處於被鎖定狀態。如果線程不處於活動狀態,則將對象頭設置成無鎖狀態,並撤銷偏向鎖;
如果線程處於活動狀態,升級為輕量級鎖的狀態。
輕量級鎖:輕量級鎖是指當鎖是偏向鎖的時候,被第二個線程 B 所訪問,此時偏向鎖就會升級為輕量級鎖,線程 B 會通過自旋的形式嘗試獲取鎖,線程不會阻塞,從而提高性能。
當前只有一個等待線程,則該線程將通過自旋進行等待。但是當自旋超過一定的次數時,輕量級鎖便會升級為重量級鎖;當一個線程已持有鎖,另一個線程在自旋,而此時又有第三個線程來訪時,輕量級鎖也會升級為重量級鎖。
重量級鎖:指當有一個線程獲取鎖之后,其余所有等待獲取該鎖的線程都會處於阻塞狀態。
重量級鎖通過對象內部的監視器(monitor)實現,而其中 monitor 的本質是依賴於底層操作系統的 Mutex Lock 實現,操作系統實現線程之間的切換需要從用戶態切換到內核態,切換成本非常高。
鎖狀態對比:
部分內容摘自:
- Java 自學指南
- Java 面試題匯總PC端瀏覽【點這里】
- Java知識圖譜
- Java 面試題匯總小程序瀏覽,掃二維碼
所有資源資源匯總於公眾號