成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Synchronized 優(yōu)化手段之鎖膨脹機(jī)制!

開發(fā) 前端
在眾多優(yōu)化方案中,鎖膨脹機(jī)制是提升 synchronized 性能最有利的手段之一(其他優(yōu)化方案我們后面再講),本文我們重點(diǎn)來看什么是鎖膨脹?以及鎖膨脹的各種細(xì)節(jié)。

[[414960]]

本文轉(zhuǎn)載自微信公眾號「Java中文社群」,作者磊哥。轉(zhuǎn)載本文請聯(lián)系Java中文社群公眾號。

synchronized 在 JDK 1.5 之前性能是比較低的,在那時我們通常會選擇使用 Lock 來替代 synchronized。然而這個情況在 JDK 1.6 時就發(fā)生了改變,JDK 1.6 中對 synchronized 進(jìn)行了各種優(yōu)化,性能也得到了大幅的提升,這也是目前版本中還能經(jīng)常見到 synchronized 身影的重要原因之一。當(dāng)然除了性能之外,synchronized 的使用也非常便利,這也是它流行的重要原因。

在眾多優(yōu)化方案中,鎖膨脹機(jī)制是提升 synchronized 性能最有利的手段之一(其他優(yōu)化方案我們后面再講),本文我們重點(diǎn)來看什么是鎖膨脹?以及鎖膨脹的各種細(xì)節(jié)。

正文

在 JDK 1.5 時,synchronized 需要調(diào)用監(jiān)視器鎖(Monitor)來實(shí)現(xiàn),監(jiān)視器鎖本質(zhì)上又是依賴于底層的操作系統(tǒng)的 Mutex Lock(互斥鎖)實(shí)現(xiàn)的,互斥鎖在進(jìn)行釋放和獲取的時候,需要從用戶態(tài)轉(zhuǎn)換到內(nèi)核態(tài),這樣就造成了很高的成本,也需要較長的執(zhí)行時間,這種依賴于操作系統(tǒng) Mutex Lock 實(shí)現(xiàn)的鎖我們稱之為“重量級鎖”。

什么是用戶態(tài)和內(nèi)核態(tài)?

用戶態(tài)(User Mode):當(dāng)進(jìn)程在執(zhí)行用戶自己的代碼時,則稱其處于用戶運(yùn)行態(tài)。內(nèi)核態(tài)(Kernel Mode):當(dāng)一個任務(wù)(進(jìn)程)執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時,我們就稱進(jìn)程處于內(nèi)核運(yùn)行態(tài),此時處理器處于特權(quán)級最高的內(nèi)核代碼中執(zhí)行。

為什么分內(nèi)核態(tài)和用戶態(tài)?

假設(shè)沒有內(nèi)核態(tài)和用戶態(tài)之分,程序就可以隨意讀寫硬件資源了,比如隨意讀寫和分配內(nèi)存,這樣如果程序員一不小心將不適當(dāng)?shù)膬?nèi)容寫到了不該寫的地方,很可能就會導(dǎo)致系統(tǒng)崩潰。

而有了用戶態(tài)和內(nèi)核態(tài)的區(qū)分之后,程序在執(zhí)行某個操作時會進(jìn)行一系列的驗證和檢驗之后,確認(rèn)沒問題之后才可以正常的操作資源,這樣就不會擔(dān)心一不小心就把系統(tǒng)搞壞的情況了,也就是有了內(nèi)核態(tài)和用戶態(tài)的區(qū)分之后可以讓程序更加安全的運(yùn)行,但同時兩種形態(tài)的切換會導(dǎo)致一定的性能開銷。

鎖膨脹

在 JDK 1.6 時,為了解決獲取鎖和釋放鎖帶來的性能消耗,引入了“偏向鎖”和“輕量級鎖”的狀態(tài),此時 synchronized 的狀態(tài)總共有以下 4 種:

  1. 無鎖
  2. 偏向鎖
  3. 輕量級鎖
  4. 重量級鎖

鎖的級別按照上述先后順序依次升級,我們把這個升級的過程稱之為“鎖膨脹”。

PS:到現(xiàn)在為止,鎖的升級是單向的,也就是說只能從低到高升級(無鎖 -> 偏向鎖 -> 輕量鎖鎖 -> 重量級鎖),不會出現(xiàn)鎖降級的情況。

鎖膨脹為什么能優(yōu)化 synchronized 的性能?當(dāng)我們了解了這些鎖狀態(tài)之后自然就會有答案,下面我們一起來看。

1.偏向鎖

HotSpot 作者經(jīng)過研究實(shí)踐發(fā)現(xiàn),在大多數(shù)情況下,鎖不存在多線程競爭,總是由同一線程多次獲得的,為了讓線程獲得鎖的代價更低,于是就引進(jìn)了偏向鎖。

偏向鎖(Biased Locking)指的是,它會偏向于第一個訪問鎖的線程,如果在運(yùn)行過程中,同步鎖只有一個線程訪問,不存在多線程爭用的情況,則線程是不需要觸發(fā)同步的,這種情況下會給線程加一個偏向鎖。

偏向鎖執(zhí)行流程

當(dāng)一個線程訪問同步代碼塊并獲取鎖時,會在對象頭的 Mark Word 里存儲鎖偏向的線程 ID,在線程進(jìn)入和退出同步塊時不再通過 CAS 操作來加鎖和解鎖,而是檢測 Mark Word 里是否存儲著指向當(dāng)前線程的偏向鎖,如果 Mark Word 中的線程 ID 和訪問的線程 ID 一致,則可以直接進(jìn)入同步塊進(jìn)行代碼執(zhí)行,如果線程 ID 不同,則使用 CAS 嘗試獲取鎖,如果獲取成功則進(jìn)入同步塊執(zhí)行代碼,否則會將鎖的狀態(tài)升級為輕量級鎖。

偏向鎖的優(yōu)點(diǎn)

偏向鎖是為了在無多線程競爭的情況下,盡量減少不必要的鎖切換而設(shè)計的,因為鎖的獲取及釋放要依賴多次 CAS 原子指令,而偏向鎖只需要在置換線程 ID 的時候執(zhí)行一次 CAS 原子指令即可。

Mark Word 擴(kuò)展知識:內(nèi)存布局

在 HotSpot 虛擬機(jī)中,對象在內(nèi)存中存儲的布局可以分為以下 3 個區(qū)域:

  1. 對象頭(Header)
  2. 實(shí)例數(shù)據(jù)(Instance Data)
  3. 對齊填充(Padding)

對象頭中又包含了:

  1. Mark Word(標(biāo)記字段):我們的偏向鎖信息就是存儲在此區(qū)域的。
  2. Klass Pointer(Class 對象指針)

對象在內(nèi)存中的布局如下:

在 JDK 1.6 中默認(rèn)是開啟偏向鎖的,可以通過“-XX:-UseBiasedLocking=false”命令來禁用偏向鎖。

2.輕量級鎖

引入輕量級鎖的目的是在沒有多線程競爭的前提下,減少傳統(tǒng)的重量級鎖使用操作系統(tǒng) Mutex Lock(互斥鎖)產(chǎn)生的性能消耗。如果使用 Mutex Lock 每次獲取鎖和釋放鎖的操作都會帶來用戶態(tài)和內(nèi)核態(tài)的切換,這樣系統(tǒng)的性能開銷是很大的。

當(dāng)關(guān)閉偏向鎖或者多個線程競爭偏向鎖時就會導(dǎo)致偏向鎖升級為輕量級鎖,輕量級鎖的獲取和釋放都通過 CAS 完成的,其中鎖獲取可能會通過一定次數(shù)的自旋來完成。

注意事項

需要強(qiáng)調(diào)一點(diǎn):輕量級鎖并不是用來代替重量級鎖的,它的本意是在沒有多線程競爭的前提下,減少傳統(tǒng)的重量級鎖使用產(chǎn)生的性能消耗。輕量級鎖所適應(yīng)的場景是線程交替執(zhí)行同步塊的情況,如果同一時間多個線程同時訪問時,就會導(dǎo)致輕量級鎖膨脹為重量級鎖。

3.重量級鎖

synchronized 是依賴監(jiān)視器 Monitor 實(shí)現(xiàn)方法同步或代碼塊同步的,代碼塊同步使用的是 monitorenter 和 monitorexit 指令來實(shí)現(xiàn)的,monitorenter 指令是在編譯后插入到同步代碼塊的開始位置,而 monitorexit 是插入到方法結(jié)束處和異常處的,任何對象都有一個 Monitor 與之關(guān)聯(lián),當(dāng)且一個 Monitor 被持有后,它將處于鎖定狀態(tài)。

如以下加鎖代碼:

  1. public class SynchronizedToMonitorExample { 
  2.     public static void main(String[] args) { 
  3.         int count = 0; 
  4.         synchronized (SynchronizedToMonitorExample.class) { 
  5.             for (int i = 0; i < 10; i++) { 
  6.                 count++; 
  7.             } 
  8.         } 
  9.         System.out.println(count); 
  10.     } 

當(dāng)我們將上述代碼編譯成字節(jié)碼之后,它的內(nèi)容是這樣的:

從上述結(jié)果可以看出,在 main 方法的執(zhí)行中多個 monitorenter 和 monitorexit 的指令,由此可知 synchronized 是依賴 Monitor 監(jiān)視器鎖實(shí)現(xiàn)的,而監(jiān)視器鎖又是依賴操作系統(tǒng)的互斥鎖(Mutex Lock),互斥鎖在每次獲取和釋放鎖時,都會帶來用戶態(tài)和內(nèi)核態(tài)的切換,這樣就增加了系統(tǒng)的性能開銷。

總結(jié)

synchronized 在 JDK 1.6 時優(yōu)化了其性能,在一系列優(yōu)化的手段中,鎖膨脹是提升 synchronized 執(zhí)行效率的關(guān)鍵手段之一,鎖膨脹指的是 synchronized 會從無鎖狀態(tài)、到偏向鎖、到輕量級鎖,最后到重量級鎖的過程。重量級之前的所有狀態(tài)在絕大數(shù)情況下可以大幅的提升 synchronized 的性能。

 

責(zé)任編輯:武曉燕 來源: Java中文社群
相關(guān)推薦

2011-11-28 12:31:20

JavaJVM

2022-07-04 08:01:01

鎖優(yōu)化Java虛擬機(jī)

2025-03-26 00:55:00

2023-06-09 07:59:37

多線程編程鎖機(jī)制

2024-04-17 12:58:15

MySQL索引數(shù)據(jù)庫

2021-01-14 08:58:12

Synchronize鎖操作

2024-12-16 00:52:26

MySQL數(shù)據(jù)庫并發(fā)

2019-10-17 08:51:00

Java悲觀鎖Monitor

2022-03-08 08:44:13

偏向鎖Java內(nèi)置鎖

2016-08-30 14:15:27

數(shù)據(jù)庫DBASQL

2024-08-13 14:08:25

2009-12-08 10:07:29

2024-03-14 08:17:33

JVMJava對象

2025-03-26 01:25:00

MySQL優(yōu)化事務(wù)

2024-03-07 17:21:12

HotSpotJVMHot Code

2024-04-19 08:05:26

鎖升級Java虛擬機(jī)

2020-04-24 15:44:50

MySQL數(shù)據(jù)庫鎖機(jī)制

2024-08-28 08:00:00

2023-11-08 08:18:19

鎖升級多線程

2020-05-07 08:07:57

synchronize線程
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 特级黄一级播放 | 欧美综合视频 | 一级日韩 | 青青久久| 国产日韩精品久久 | 久久精品亚洲精品国产欧美 | 亚洲精品久久久一区二区三区 | 美女一区二区在线观看 | 亚洲精品久久久久久一区二区 | 91超碰caoporn97人人 | 日本不卡一区二区三区 | 热99在线| 香蕉视频一区二区 | 一区二区亚洲 | 欧美日韩在线不卡 | 欧美一级免费看 | 午夜精品久久 | 黄色综合 | 久久精品亚洲精品国产欧美 | 久久久999精品 | av一二三区| 一区二区国产精品 | 亚洲成人免费 | 成人免费看黄网站在线观看 | 久久精品二区 | 91天堂网 | 中文字幕一级毛片视频 | 在线激情视频 | 亚洲精品一区二区在线观看 | 国产偷录叫床高潮录音 | 国产欧美精品一区二区三区 | 欧美午夜在线 | 欧美综合一区二区 | 一区二区三区观看视频 | 国产精品二区三区 | 高清亚洲 | 久久久av| 亚洲精品成人av久久 | 精品国产视频 | 狠狠色综合网站久久久久久久 | 中文字幕二区三区 |