java-鎖得升級(概念):偏向鎖--輕量級鎖--重量級鎖

偏向鎖:

  • 在大多數情況下,鎖不僅僅不存在多線程的競爭,而且總是由同一個線程多次獲得。在這個背景下就設計了偏向鎖。偏向鎖,顧名思義,就是鎖偏向於某個線程。
  • 當一個線程訪問加了同步鎖的代碼塊時,會在對象頭中存儲當前線程的ID,後續這個線程進入和退出這段加了同步鎖的代碼塊時,不需要再次加鎖和釋放鎖。而是直接比較對象頭裏面是否存儲了指向當前線程的偏向鎖。如果相等表示偏向鎖是偏向於當前線程的,就不需要再嘗試獲得鎖了,引入偏向鎖是爲了在無多線程競爭的情況下儘量減少不必要的輕量級鎖執行路徑。(偏向鎖的目的是消除數據在無競爭情況下的同步原語,進一步提高程序的運行性能。)

輕量級鎖

如果偏向鎖被關閉或者當前偏向鎖已經已經被其他線程獲取,那麼這個時候如果有線程去搶佔同步鎖時,鎖會升級到輕量級鎖。

重量級鎖

  • 如果當前爲輕量級鎖,當前線程去搶佔鎖但是發現鎖已經被佔用,那他會進入自旋(重試),1.6以前默認自旋10次,如果還是沒有獲取到鎖,那他會升級膨脹,升級到重量級鎖並阻塞;(注:1.6之後 自適應自旋鎖:會根據上一次搶佔時間去決定當前搶佔隨時間的長短,如果上一次自旋時間很長,那這次就短,如果上次短,那這次就長一些)。
  • 多個線程競爭同一個鎖的時候,虛擬機會阻塞加鎖失敗的線程,並且在目標鎖被釋放的時候,喚醒這些線程;
  • Java 線程的阻塞以及喚醒,都是依靠操作系統來完成的:os pthread_mutex_lock() ;
  • 升級爲重量級鎖時,鎖標誌的狀態值變爲“10”,此時Mark Word中存儲的是指向重量級鎖的指針,此時等待鎖的線程都會進入阻塞狀態

整理:

  • 偏向鎖只有在第一次請求時採用CAS在鎖對象的標記中記錄當前線程的地址,在之後該線程再次進入同步代碼塊時,不需要搶佔鎖,直接判斷線程ID即可,這種適用於鎖會被同一個線程多次搶佔的情況。
  • 輕量級鎖才用CAS操作,把鎖對象的標記字段替換爲一個指針指向當前線程棧幀中的LockRecord,該工件存儲鎖對象原本的標記字段,它針對的是多個線程在不同時間段內申請通一把鎖的情況。
  • 重量級鎖會阻塞、和喚醒加鎖的線程,它適用於多個線程同時競爭同一把鎖的情況。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章