對象字節碼看併發編程的底層實現

線程模型

在這裏插入圖片描述

對於 Hotspot 來說,每一個 Java 線程,都會映射到一條輕量級進程中(LWP,Light Weight Process)。輕量級進程是用戶進程調用系統內核所提供的一套接口,實際上它還需要調用更加底層的內核線程(KLT,Kernel-Level Thread)。而具體的功能,比如創建、同步等,則需要進行系統調用。

這些系統調用的操作,代價都比較高,需要在用戶態(User Mode)和內核態(Kernel Mode)中來回切換,也就是我們常說的線程上下文切換( CS,Context Switch)。

對象內存佈局

在這裏插入圖片描述

Mark Word:用來存儲 hashCode、GC 分代年齡、鎖類型標記、偏向鎖線程 ID、CAS 鎖指向線程 LockRecord 的指針等,synconized 鎖的機制與這裏密切相關,這有點像 TCP/IP 中的協議頭。

Class Pointer:用來存儲對象指向它的類元數據指針、JVM 就是通過它來確定是哪個 Class 的實例。
Instance Data:存儲的是對象真正有效的信息,比如對象中所有字段的內容。
Padding:HostSpot 規定對象的起始地址必須是 8 字節的整數倍,這是爲了高效讀取對象而做的一種“對齊”操作

可重入鎖
synchronized 是一把可重入鎖。因此,在一個線程使用 synchronized 方法時可以調用該對象的另一個 synchronized 方法,即一個線程得到一個對象鎖後再次請求該對象鎖,是可以永遠拿到鎖的。

Java 中線程獲得對象鎖的操作是以線程而不是以調用爲單位的。synchronized 鎖的對象頭的 Mark Work 中會記錄該鎖的線程持有者和計數器。當一個線程請求成功後,JVM 會記下持有鎖的線程,並將計數器計爲 1 。此時如果有其他線程請求該鎖,則必須等待。而該持有鎖的線程如果再次請求這個鎖,就可以再次拿到這個鎖,同時計數器會遞增。當線程退出一個 synchronized 方法/塊時,計數器會遞減,如果計數器爲 0 則釋放該鎖。

鎖升級
根據使用情況,鎖升級大體可以按照下面的路徑:偏向鎖→輕量級鎖→重量級鎖,鎖只能升級不能降級,所以一旦鎖升級爲重量級鎖,就只能依靠操作系統進行調度。

我們再看一下 Mark Word 的結構。其中,Biased 有 1 bit 大小,Tag 有 2 bit 大小,鎖升級就是通過 Thread Id、Biased、Tag 這三個變量值來判斷的。

在這裏插入圖片描述

偏向鎖
偏向鎖,其實是一把偏心鎖(一般不這麼描述)。在 JVM 中,當只有一個線程使用了鎖的情況下,偏向鎖才能夠保證更高的效率。

當第 1 個線程第一次訪問同步塊時,會先檢測對象頭 Mark Word 中的標誌位(Tag)是否爲 01,以此來判斷此時對象鎖是否處於無鎖狀態或者偏向鎖狀態(匿名偏向鎖)。

這也是鎖默認的狀態,線程一旦獲取了這把鎖,就會把自己的線程 ID 寫到 Mark Word 中,在其他線程來獲取這把鎖之前,該線程都處於偏向鎖狀態。

輕量級鎖

當下一個線程參與到偏向鎖競爭時,會先判斷 Mark Word 中保存的線程 ID 是否與這個線程 ID 相等,如果不相等,則會立即撤銷偏向鎖,升級爲輕量級鎖。

輕量級鎖的獲取是怎麼進行的呢?它們使用的是自旋方式

參與競爭的每個線程,會在自己的線程棧中生成一個 LockRecord ( LR ),然後每個線程通過 CAS(自旋)的操作將鎖對象頭中的 Mark Work 設置爲指向自己的 LR 指針,哪個線程設置成功,就意味着哪個線程獲得鎖。在這種情況下,JVM 不會依賴內核進行線程調度。

當鎖處於輕量級鎖的狀態時,就不能夠再通過簡單的對比 Tag 值進行判斷了,每次對鎖的獲取,都需要通過自旋的操作。

當然,自旋也是面向不存在鎖競爭的場景,比如一個線程運行完了,另外一個線程去獲取這把鎖。但如果自旋失敗達到一定的次數(JVM 自動管理)時,就會膨脹爲重量級鎖。

重量級鎖
重量級鎖即爲我們對 synchronized 的直觀認識,在這種情況下,線程會掛起,進入到操作系統內核態,等待操作系統的調度,然後再映射回用戶態。系統調用是昂貴的,重量級鎖的名稱也由此而來。

如果系統的共享變量競爭非常激烈,那麼鎖會迅速膨脹到重量級鎖,這些優化也就名存實亡了。如果併發非常嚴重,則可以通過參數 -XX:-UseBiasedLocking 禁用偏向鎖。這種方法在理論上會有一些性能提升,但實際上並不確定

因爲,synchronized 在 JDK,包括一些框架代碼中的應用是非常廣泛的。在一些不需要同步的場景中,即使加上了 synchronized 關鍵字,由於鎖升級的原因,效率也不會太差。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章