Java內置鎖synchronized的實現原理

簡述
Java中每一個對象均可以用來實現一個同步的鎖,這些鎖被稱爲內置鎖(Intrinsic Lock)或監視器鎖(Monitor Lock)。html

具體表現形式以下:數組

一、普通同步方法,鎖的是當前實例對象佈局

二、靜態同步方法,鎖的是當前Class對象spa

三、對於同步代碼塊,鎖的是Synchronized括號中的代碼塊線程

線程在進入同步代碼塊以前會自動獲取鎖,而且在退出同步代碼塊時自動釋放鎖,不管是經過正常路徑退出,仍是經過代碼塊中拋出異常退出。得到內置鎖的惟一途徑就是進入由這個鎖保護的同步方法或代碼塊。指針

從 JVM 規範 中 能夠 看到 Synchonized 在 JVM 裏 的 實現 原理, JVM 基於 進入 和 退出 Monitor 對象 來 實現 方法 同步 和 代碼 塊 同步, 但 二者 的 實現 細節 不同。 代碼 塊 同步 是 使用 monitorenter 和 monitorexit 指令 實現 的, 而 方法 同步 是 使用 另外 一種 方式 實現 的, 細節 在 JVM 規範 裏 並無 詳細 說明。 可是, 方法 的 同步 一樣 能夠 使用 這 兩個 指令 來 實現。htm

monitorenter 指令 是在 編譯 後 插入 到 同步 代碼 塊 的 開始 位置, 而 monitorexit 是 插入 到 方法 結束 處 和 異常 處, JVM 要 保證 每一個 monitorenter 必須 有 對應 的 monitorexit 與之 配對。 任何 對象 都有 一個 monitor 與之 關聯, 當 且 一個 monitor 被 持有 後, 它將 處於 鎖定 狀態。 線程 執行 到 monitorenter 指令時, 將會 嘗試 獲取 對象 所 對應 的 monitor 的 全部權, 即 嘗試 得到 對象 的 鎖。對象

 

對象的內存佈局

在HotSpot虛擬機中,對象在內存中存儲的佈局能夠分爲3塊區域:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)。blog

synchronized 用的鎖 是 存在 對象頭 中。
若是 對象是數組類型, 則虛擬機用 3 個字 寬( Word) 存儲 對 象頭, 若是對象是非數組類型, 則用 2字寬存儲 對 象頭。 在 32位虛擬 機中, 1 字 寬 等於 4 字節, 即 32bit。

繼承

  • HotSpot虛擬機的對象頭包括兩部分信息:
  1. Mark Word   第一部分用於存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分數據的長度在32位和64位的虛擬機(未開啓壓縮指針)中分別爲32bit和64bit。
  2. 類型指針       對象頭的另一部分是類型指針,即對象指向它的類元數據的指針,虛擬機經過這個指針來肯定這個對象是哪一個類的實例。並非全部的虛擬機實現都必須在對象數據上保留類型指針,換句話說,查找對象的元數據信息並不必定要通過對象自己,這點將在2.3.3節討論。
  • 實例數據部分是對象真正存儲的有效信息,也是在程序代碼中所定義的各類類型的字段內容。不管是從父類繼承下來的,仍是在子類中定義的,都須要記錄起來。這部分的存儲順序會受到虛擬機分配策略參數(FieldsAllocationStyle)和字段在Java源碼中定義順序的影響。
  • 對齊填充並非必然存在的,也沒有特別的含義,它僅僅起着佔位符的做用

 

      詳見 https://www.cnblogs.com/kaleidoscope/p/9699329.html 

相關文章
相關標籤/搜索