一夜搞懂 JVM 執行緒安全與鎖優化

2022-05-22 13:09:06 字數 2956 閱讀 7659

我的 github 部落格

之前我們學習了記憶體模型和執行緒,了解了jmm和執行緒,初步**了jvm怎麼實現併發,而本篇文章,我們的關注點是jvm如何實現高效

併發程式設計的目的是為了讓程式執行得更快,提高程式的響應速度,雖然我們希望通過多執行緒執行任務讓程式執行得更快,但是同時也會面臨非常多的挑戰,比如像執行緒安全問題、執行緒上下文切換的問題、硬體和軟體資源限制等問題,這些都是併發程式設計給我們帶來的難題。

其中執行緒安全問題是我們最關心的問題之一,我們接下來主要就圍繞著執行緒安全的問題來展開。

2.1.1 定義

當多個執行緒訪問乙個物件時,如果不用考慮這些執行緒在執行時環境下的排程和交替執行,也不需要進行額外的同步,或者在呼叫方進行任何其他的協調操作,呼叫這個物件的行為都可以獲得正確的結果,那這個物件是執行緒安全的

要求執行緒安全的**都必須具備乙個特徵

**本身封裝了所有必要的正確性保障手段(如互斥同步等),令呼叫者無須關心多執行緒的問題,更無須自己採取任何措施來保證多執行緒的正確呼叫。

2.1.2 分類
下面將按照執行緒安全的程度由強至弱分成五類

例子:thread類的suspend()resume(),乙個嘗試中斷執行緒,乙個嘗試恢復執行緒,在併發條件下,有可能會造成死鎖

2.1.3 實現
可分成兩大手段:

本篇重點在虛擬機器本身

1.互斥同步
​ b.使用重入鎖reentrantlock

​ 之前在 高階之路 | 奇妙的 thread 之旅中也提到過重入鎖的使用,相信看過的讀者還有一些印象

2.非阻塞同步
3.無同步方案
a.可重入**/純**b.執行緒本地儲存

2.2.1 適應性自旋

注意:自旋等待不能代替阻塞,它雖然能避免執行緒切換的開銷,但會占用處理器時間,因此自旋等待的時間必須要有一定的限度,如果自旋超過了限定的次數(預設10次)仍未成功獲鎖,就需要掛執行緒了

2.2.2 鎖消除

2.2.3 鎖粗化

2.2.4 輕量級鎖

首先先理解hotspot虛擬機器的物件頭的記憶體布局:分為兩部分

2.之後虛擬機會嘗試用cas操作將物件的mark word更新為指向lock record的指標。若更新動作成功,那麼當前執行緒就擁有了該物件的鎖,且物件mark word的鎖標誌位變為00,即處於輕量級鎖定狀態;反之,虛擬機會先檢查物件的mark word是否指向當前執行緒的棧幀,若是,則當前執行緒已有該物件的鎖,可直接進入同步塊繼續執行,否則說明改物件已被其他執行緒搶占。如下圖:

另外,如果有兩條以上的執行緒爭用同乙個鎖,那輕量級鎖就不再有效,要膨脹為重量級鎖,鎖標誌位變為10mark word中儲存的就是指向重量級鎖的指標,後面等待鎖的執行緒也要進入阻塞狀態

q:處於輕量級鎖狀態時,會不會使用自旋鎖這個競爭機制

a:執行緒首先會通過cas獲取鎖,失敗後通過自旋鎖來嘗試獲取鎖,再失敗鎖就膨脹為重量級鎖。所以輕量級鎖狀態下可能會有自旋鎖的參與(cas將物件頭的標記指向鎖記錄指標失敗的時候)

2.2.5 偏向鎖

能夠寫出高效能、高伸縮性的併發程式是一門藝術,而了解併發在底層是如何實現的,則是掌握這門藝術的前提,也是成長為高階程式設計師的必備知識!

加油吧!騷年!以夢為馬,不負韶華!

如果文章對您有一點幫助的話,希望您能點一下贊,您的點讚,是我前進的動力

一夜搞懂 JVM 位元組碼執行引擎

我的 github 部落格 編譯的結果從本地機器碼轉變為位元組碼,是儲存格式發展的一小步,卻是程式語言發展的一大步 首先,丟擲靈魂三問 如果你對上述問題理解得還不是特別透徹的話,可以看下這篇文章 如果理解了,你可以關閉網頁,開啟遊戲放鬆了hhh 下面,筆者將帶你 jvm核心的組成部分之一 執行引擎。...

JVM執行緒安全與鎖優化

1.不可變 不可變的物件一定是執行緒安全的。如string類。2.絕對執行緒安全 3.相對執行緒安全 4.執行緒相容 5.執行緒對立 1.互斥同步 阻塞式同步 1 同步指的是 多個執行緒併發訪問共享資料時,保證共享資料在同一時刻只能被乙個執行緒使用。2 互斥指的是 同步的手段。如 臨界區 互斥量和訊...

JVM學習 (九)執行緒安全和鎖優化

從以前流行的面向過程程式設計到現在的物件導向程式設計,物件導向程式設計極大的提公升了現代軟體開發的效率和規模,但是不可避免的是物件之間的相互切換,為了讓程式維護的更好更好,我們必須引入 高效併發 來保證併發的正確性 安全性和效率性。比較寬泛的定義 沒有什麼可以操作性 如果乙個物件可以被多個執行緒同時...