自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java程序員必會Synchronized底層原理剖析

開發(fā) 前端
ynchronized是Java提供一種隱式鎖,無需開發(fā)者手動加鎖釋放鎖。保證多線程并發(fā)情況下數(shù)據(jù)的安全性,實現(xiàn)了同一個時刻只有一個線程能訪問資源,其他線程只能阻塞等待,簡單說就是互斥同步。

synchronized作為Java程序員最常用同步工具,很多人卻對它的用法和實現(xiàn)原理一知半解,以至于還有不少人認(rèn)為synchronized是重量級鎖,性能較差,盡量少用。

但不可否認(rèn)的是synchronized依然是并發(fā)首選工具,連volatile、CAS、ReentrantLock都無法動搖synchronized的地位。synchronized是工作面試中的必備技能,今天就跟著一燈一塊深入剖析synchronized的底層原理。

1. synchronized作用

synchronized是Java提供一種隱式鎖,無需開發(fā)者手動加鎖釋放鎖。保證多線程并發(fā)情況下數(shù)據(jù)的安全性,實現(xiàn)了同一個時刻只有一個線程能訪問資源,其他線程只能阻塞等待,簡單說就是互斥同步。

2. synchronized用法

先看一下synchronized有哪幾種用法?

使用位置

被鎖對象

示例代碼

實例方法

??實例對象??


public synchronized void method() {

   ……

}

靜態(tài)方法

??class類??

public static synchronized void method() {

   ……

}

實例對象

??實例對象??

public void method() {

   Object obj = new Object();

   synchronized (obj) {

       ……

   }

}

類對象

??class類??

public void method() {

   synchronized (Demo.class) {

       ……

   }

}

this關(guān)鍵字

??實例對象??

public void method() {

   synchronized (this) {

       ……

   }

}

可以看到被鎖對象只要有兩種,實例對象和class類。

  • 由于靜態(tài)方法可以通過類名直接訪問,所以它跟直接加鎖在class類上是一樣的。
  • 當(dāng)在實例方法、實例對象、this關(guān)鍵字上面加鎖的時候,鎖定范圍都是當(dāng)前實例對象。
  • 實例對象上面的鎖和class類上面的鎖,兩者不互斥。

3. synchronized加鎖原理

當(dāng)我們使用synchronized在方法和對象上加鎖的時候,Java底層到底怎么實現(xiàn)加鎖的?

當(dāng)在類對象上加鎖的時候,也就是在class類加鎖,代碼如下:

/**
* @author 一燈架構(gòu)
* @apiNote Synchronized示例
**/
public class SynchronizedDemo {

public void method(){
synchronized (SynchronizedDemo.class) {
System.out.println("Hello world!");
}
}

}

反編譯一下,看一下源碼實現(xiàn):

圖片

可以看到,底層是通過monitorenter和monitorexit兩個關(guān)鍵字實現(xiàn)的加鎖與釋放鎖,執(zhí)行同步代碼之前使用monitorenter加鎖,執(zhí)行完同步代碼使用monitorexit釋放鎖,拋出異常的時候也是用monitorexit釋放鎖。

寫成偽代碼,類似下面這樣:

/**
* @author 一燈架構(gòu)
* @apiNote Synchronized示例
**/
public class SynchronizedDemo {

public void method(){
try {
monitorenter 加鎖;
System.out.println("Hello world!");
monitorexit 釋放鎖;
} catch (Exception e) {
monitorexit 釋放鎖;
}
}

}

當(dāng)在實例方法上加鎖,底層是怎么實現(xiàn)的呢?代碼如下:

/**
* @author 一燈架構(gòu)
* @apiNote Synchronized示例
**/
public class SynchronizedDemo {

public static synchronized void method(){
System.out.println("Hello world!");
}

}

再反編譯看一下底層實現(xiàn):

圖片

這次只使用了一個ACC_SYNCHRONIZED關(guān)鍵字,實現(xiàn)了隱式的加鎖與釋放鎖。其實無論是ACC_SYNCHRONIZED關(guān)鍵字,還是monitorenter和monitorexit,底層都是通過獲取monitor鎖來實現(xiàn)的加鎖與釋放鎖。

而monitor鎖又是通過ObjectMonitor來實現(xiàn)的,虛擬機(jī)中ObjectMonitor數(shù)據(jù)結(jié)構(gòu)如下(C++實現(xiàn)的):

ObjectMonitor() {
_header = NULL;
_count = 0; // WaitSet 和 EntryList 的節(jié)點(diǎn)數(shù)之和
_waiters = 0,
_recursions = 0; // 重入次數(shù)
_object = NULL;
_owner = NULL; // 持有鎖的線程
_WaitSet = NULL; // 處于wait狀態(tài)的線程,會被加入到_WaitSet
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ; // 多個線程爭搶鎖,會先存入這個單向鏈表
FreeNext = NULL ;
_EntryList = NULL ; // 處于等待鎖block狀態(tài)的線程,會被加入到該列表
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}

圖片

圖上展示了ObjectMonitor的基本工作機(jī)制:

當(dāng)多個線程同時訪問一段同步代碼時,首先會進(jìn)入 _EntryList 隊列中等待。

當(dāng)某個線程獲取到對象的Monitor鎖后進(jìn)入臨界區(qū)域,并把Monitor中的 _owner 變量設(shè)置為當(dāng)前線程,同時Monitor中的計數(shù)器 _count 加1。即獲得對象鎖。

若持有Monitor的線程調(diào)用 wait() 方法,將釋放當(dāng)前持有的Monitor鎖,_owner變量恢復(fù)為null,_count減1,同時該線程進(jìn)入 _WaitSet 集合中等待被喚醒。

在_WaitSet 集合中的線程會被再次放到_EntryList 隊列中,重新競爭獲取鎖。

若當(dāng)前線程執(zhí)行完畢也將釋放Monitor并復(fù)位變量的值,以便其他線程進(jìn)入獲取鎖。

線程爭搶鎖的過程要比上面展示得更加復(fù)雜。除了_EntryList 這個雙向鏈表用來保存競爭的線程,ObjectMonitor中還有另外一個單向鏈表 _cxq,由兩個隊列來共同管理并發(fā)的線程。

圖片

責(zé)任編輯:武曉燕 來源: 一燈架構(gòu)
相關(guān)推薦

2022-03-17 10:24:28

JavaJVM

2022-12-26 09:27:48

Java底層monitor

2019-01-30 14:14:16

LinuxUNIX操作系統(tǒng)

2018-08-06 10:25:07

Linux命令程序員

2021-01-08 08:34:09

Synchronize線程開發(fā)技術(shù)

2023-09-12 11:25:15

2024-03-15 15:12:27

關(guān)鍵字底層代碼

2021-11-02 09:54:51

Java開發(fā)工具

2023-06-09 14:01:00

架構(gòu)程序APP

2020-05-13 11:20:57

MySQL規(guī)范數(shù)據(jù)庫

2021-07-20 10:26:53

源碼底層ArrayList

2009-06-15 10:43:45

Java程序員Java程序GC

2023-10-19 15:11:48

Redis

2019-05-27 08:11:13

高并發(fā)Synchronize底層

2024-08-28 08:00:00

2023-05-11 08:01:08

Code開發(fā)保護(hù)機(jī)制

2014-02-09 10:30:17

Python程序員工具

2012-11-08 09:49:30

C++Java程序員

2013-08-20 09:33:59

程序員

2012-03-06 09:22:46

程序員
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號