Java?Synchronize底層原理總結
對象內存結構

對象頭:MarkWord 存儲對象頭的信息,Klass Word 描述對象實例的具體類型
實例數據:成員變量
對齊填充:如果對象頭 + 實例變量 不是 8 的整數倍,則通過對齊填充補齊
MarkWord 解析

hashcode:25位的對象標識Hash碼age:對象分代年齡占4位biased_lock:偏向鎖標識,占1位,0表示沒有開始偏向鎖,1表示開啟了偏向鎖thread:持有偏向鎖的線程ID,占23位epoch:偏向時間戳,占2位ptr_to_lock_record:輕量級鎖狀態(tài)下,指向棧中鎖記錄的指針,占30位ptr_to_heavyweight_monitor:重量級鎖狀態(tài)下,指向對象監(jiān)視器Monitor的指針,占30位
LockRecord 鎖記錄
Markword:記錄鎖記錄的地址
對象引用:引用被加上鎖了的對象

重量級鎖
Monitor
Monitor 監(jiān)視器,是由 jvm 提供的,由 C++ 實現的,有三個實現部分
WaitSet:調用了 wait 方法的線程在這里等待,處于 WAITED 狀態(tài)
EntryList:沒有搶到對象鎖的線程在這里等待,處于 BLOCKED 狀態(tài)
Owner:存儲已經搶到鎖的線程對象
Monitor 的實現屬于重量級鎖,涉及到 內核態(tài)和用戶態(tài)的切換,線程的上下文切換,每個 Java 對象都會關聯一個 Monitor 對象,如果使用 Synchronize 給該對象加鎖,那么 Java 對象上面的 MarkWord 地址就被設置為指向該 Monitor 對象的指針

輕量級鎖
加鎖流程:
- 在線程棧中創(chuàng)建一個
Lock Record對象,它的object reference字段指向鎖對象 - 通過 CAS 指令把
Lock Record的地址存放到對象頭的Markword中,如果是無鎖狀態(tài)則修改成功,代表該線程獲取了輕量級鎖 - 如果當前線程已經持有該鎖,就代表是一次鎖重入,設置
Lock Record的第一部分為null,起到一個重入計數器的作用 - 如果
CAS修改失敗,則說明發(fā)生了競爭,需要膨脹為重量級鎖
解鎖過程:
- 遍歷線程棧,找到所有
object reference字段等于當前鎖對象的Lock record - 如果
Lock record的MarkWord為null,代表這是一次重入,將obj設置為null后continue即可 - 如果
Lock record的Markword不為null,則利用CAS指令將對象頭的markword與對象對象頭的markword進行替換,如果成功則恢復為無鎖狀態(tài),如果失敗則膨脹為重量級鎖
Markword 記錄

開始時的狀態(tài)

替換后的狀態(tài)

偏向鎖
背景:輕量級鎖在沒有競爭的時候,每次重入都需要進行 CAS 操作
Java 6 中 引入偏向鎖來做進一步的優(yōu)化:只有第一次 操才使用 CAS 將線程 ID 設置到對象的 markword 頭,之后發(fā)現這個線程 ID 是自己就不會產生競爭,不用重新 CAS,以后只要不發(fā)生競爭,這個對象就歸這個線程所有

代碼示例:
public class Thread5 {
private static final Object object = new Object();
public static void method1() {
synchronized (object) {
method2();
}
}
public static void method2() {
synchronized (object) {
method3();
}
}
public static void method3() {
synchronized (object) {
}
}
}總結
Java 中的 Synchronize 有偏向鎖、輕量級鎖、重量級鎖三種形式,分別對應了鎖只被一個線程持有、不同線程交替持有鎖、多線程競爭的情況
重量級鎖:底層使用 Monitor 實現,里面涉及到了用戶態(tài)和內核態(tài)的轉換、進程的上下文切換,成本較高,性能比較低
輕量級鎖:線程加鎖時間是錯開的(也就是沒有競爭),可以用輕量級鎖來優(yōu)化,輕量級修改了對象頭的鎖標志,相對重量級鎖性能提升了許多,每次修改都是 CAS 操作,保證原子性
偏向鎖:一段很長的時間內都只被一個線程使用鎖,可以使用偏向鎖,第一次獲得鎖時,會有一個 CAS 操作,之后該線程再獲取鎖,只需要判斷 mark word 中是否是自己的線程 id 即可,而不是開銷相對較大的 CAS 命令
以上就是Java Synchronize底層原理總結的詳細內容,更多關于Java Synchronize底層原理的資料請關注腳本之家其它相關文章!
相關文章
SpringCloud服務接口調用OpenFeign及使用詳解
這篇文章主要介紹了SpringCloud服務接口調用——OpenFeign,在學習Ribbon時,服務間調用使用的是RestTemplate+Ribbon實現,而Feign在此基礎上繼續(xù)進行了封裝,使服務間調用變得更加方便,需要的朋友可以參考下2023-04-04
SpringCloud Config分布式配置中心使用教程介紹
springcloud config是一個解決分布式系統的配置管理方案。它包含了 client和server兩個部分,server端提供配置文件的存儲、以接口的形式將配置文件的內容提供出去,client端通過接口獲取數據、并依據此數據初始化自己的應用2022-12-12

