輕量級、重量級鎖都是啥玩意兒

大綱

前言

在JDK1.6之後,爲了減小消耗,鎖進行了不少的升級。而且有了四種狀態,從低到高git

  • 無鎖狀態
  • 偏向鎖狀態
  • 輕量級鎖狀態
  • 重量級鎖狀態

不一樣等級間的鎖能夠進行升級,可是不能進行降級github

下面就介紹一下這四種不一樣等級的鎖spring


個人全部文章同步更新與Github--Java-Notes,想了解JVM(基本更完),HashMap源碼分析,spring相關,,併發,劍指offer題解(Java版),能夠點個star。能夠看個人github主頁,天天都在更新喲。多線程

邀請您跟我一同完成 repo併發


對象內存佈局

在講鎖以前咱們應該瞭解對象的內存佈局,由於後面鎖的斷定時須要用到,源碼分析

該內容能夠看個人這篇文章,對象的內存佈局,重點看對象頭中的運行時數據(Mark Word)佈局

看了這個你應該知道,Mark Word(之後簡稱MW) 會隨着 標誌位的變化而變化性能

MW變化

先把他放出來,省得等會兒你本身翻線程

無鎖狀態

能夠看到,這種狀況下,MW被分爲了四個部分,他鎖的標誌位爲 01,是不是偏向鎖標誌位爲 0.3d

偏向鎖(biasedLock)

先看MW變化(在對象頭變化的那一張圖片中)

能夠看到,他的鎖標誌位無鎖的標誌位是同樣的 都是 01,可是是不是偏向鎖的標誌位就變了 變成了 1.而且整個MW部分變成了5部分

目的

通過研究發現,大多數狀況下,鎖不只不存在多線程競爭,並且老是由同一線程屢次得到,爲了讓線程得到鎖代價更低而引人了偏向鎖

偏向鎖,就如同他的名字同樣,"偏向","偏愛",英文"biased"也是偏心的意思。

他爲啥是叫這個呢,由於這個鎖偏向於第一個獲取到他的線程,若是在接下來的執行過程當中,該鎖沒有被其餘的線程獲取,則持有偏向鎖的線程將永遠不須要再進行同步

步驟

上面一共被分爲三大部分,

  • 無鎖狀態
  • 偏向鎖狀態
  • 撤銷偏向鎖

上面的圖中,線程一演示了偏向鎖的初始化流程,線程2演示了偏向鎖撤銷的過程

初始化過程

  • 當鎖對象第一次被線程獲取的時候,虛擬機會將對象頭中的鎖標誌位置爲 "01"(偏向模式)
  • 同時,使用CAS(若是不瞭解CAS,能夠看這篇文章,悲觀鎖和樂觀鎖)操做,把獲取到這個鎖的線程的ID記錄在對象的MW中,
  • 若是 CAS成功,持有偏向鎖的線程每次進入這個鎖相關的同步塊時,虛擬機能夠不進行任何同步操做

撤銷過程

  • 首先暫停擁有偏向鎖的線程
  • 而後檢查持有偏向鎖的線程是否活着
    • 不活躍,將對象頭設置成無鎖狀態 (標誌位"01",但不可偏向)
    • 活,
      • CAS成功,從新偏向,更改線程ID
      • 失敗,恢復成無鎖狀態,或者變成輕量級鎖定狀態。

輕量級鎖

標誌位爲"00",能夠看最開始的圖

爲啥叫輕量級鎖,由於這是相比於傳統的重量級鎖而言,原來傳統的重量級鎖,使用的是系統互斥量實現的

他的出現並非代替重量級鎖,而是在沒有多線程競爭的前提下,減小系統互斥量操做產生的性能消耗

步驟

先看圖

加鎖

  • 線程在執行同步塊以前,JVM會如今當前線程的棧幀中建立用於存儲鎖記錄(下圖的LockRecord)的空間,並將對象頭中的MW複製到鎖記錄中,官方稱爲 Displaced Mark Word
  • 而後,虛擬機將使用CAS操做,將對象的MW更新爲指向鎖記錄的指針
    • 若是這個操做成功,那麼該線程就有了該對象的鎖,而且對象的MW的鎖標誌位置爲 "00",表示該對象處於輕量級鎖定狀態
    • 若是更新失敗,表示其餘線程競爭鎖,當前線程嘗試使用自旋來獲取鎖

解鎖

  • 使用CAS操做將 Displaced Mark Word 替換回到對象頭
    • 若是成功,則說明沒有發生競爭
    • 失敗,則表示當前鎖存在競爭,鎖就會膨脹成重量級鎖
      • 釋放鎖,而且喚醒等待的線程

缺點

輕量級能提高程序同步性能的依據是"對於絕大部分的鎖,在整個同步週期內都是不存在競爭的",這是一個經驗數據。

  • 若是沒有競爭,輕量級鎖使用CAS操做,避免使用互斥量
  • 若是存在競爭,除了互斥量的開銷,還有 CAS的操做,不只沒有提高,反而性能會降低

各個鎖之間的轉換

對比

優勢 缺點 適用場景
偏向鎖 加鎖和解鎖都不須要額外的消耗,和執行非同步方法相比僅存在納秒級的差距 若是線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 只有一個線程訪問同步塊
輕量級鎖 競爭的線程不會阻塞,提升了程序的響應速度 若是始終得不到鎖競爭的線程,使用自旋會消耗CPU 追求響應時間
同步塊執行速度很是塊
重量級鎖 線程競爭不使用自旋,不會消耗CPU 線程阻塞,響應時間慢 追求吞吐量同步塊執行時間較長
相關文章
相關標籤/搜索