1. 程式人生 > >Java偏向鎖\輕量級鎖\重量級鎖總結

Java偏向鎖\輕量級鎖\重量級鎖總結

 

資源消耗

目的

場景

實現方式

偏向鎖

一個執行緒只有一次CAS

單執行緒進行同步塊時,消除輕量級鎖的CAS操作。

大多數場景為單執行緒訪問同步塊,一旦有競爭,偏向鎖失效。

判斷markword是否指現當前執行緒

輕量級鎖

每次進出同步塊,都要進行CAS設定Mark word,出現鎖競爭時,自旋獲得鎖,不進行使用者態與核心態切換。

以自旋與CAS操作的方式進行執行緒同步,減少執行緒態切換帶來的效能問題

追求相應時間;

同步塊執行很快時,一旦超過自旋閾值,則升級為重量級鎖

判斷markword是否指現當前執行緒的 lock record

重量級鎖

每次進出同步塊,都要進行CAS設定Mark word,出現鎖競爭時,執行緒阻塞掛起,進行使用者態與核心態切換。

執行緒同步

追求吞吐量;

同步塊執行時間長

判斷markword是否指現鎖對像。

 

偏向鎖

Java偏向鎖旨在對於無併發爭用的前提下,進行真正意義上的無鎖同步。個人理解就是執行緒在獲取鎖之前先檢查是否偏向,偏向了就直接拿物件頭中儲存的執行緒ID與當前執行緒做比較,如果一致就繼續執行,不一致就撤銷偏向,走無偏向鎖定流程。

關於這裡面的撤銷偏向,是通知已經獲取偏向鎖的執行緒撤銷(也就是物件頭記錄的執行緒ID),還是爭用偏向鎖的執行緒(即當前執行緒)撤銷呢?撤銷的具體過程又是什麼樣的呢?

1、偏向鎖升級:一個物件剛開始例項化的時候,沒有任何執行緒來訪問它的時候。它是可偏向的,意味著,它現在認為只可能有一個執行緒來訪問它。

hash

age

是否偏向鎖:1

鎖標識位:01

2、所以當第一個執行緒來訪問它的時候,它會偏向這個執行緒,此時,物件持有偏向鎖。偏向第一個執行緒,這個執行緒在修改物件頭MarkWord成為偏向鎖的時候使用

CAS操作,並將物件頭中的ThreadID改成自己的ID,之後再次訪問這個物件時,只需要對比ID,不需要再使用CAS在進行操作。

執行緒ID

epoch

age

是否偏向鎖:1

鎖標識位:01

3、一旦有第二個執行緒訪問這個物件,因為偏向鎖不會主動釋放,所以第二個執行緒可以看到物件時偏向狀態,這時表明在這個物件上已經存在競爭了,檢查原來持有該物件鎖的執行緒是否依然存活,如果掛了,則可以將物件變為無鎖狀態,然後重新偏向新的執行緒。

設定成無鎖狀態。????無鎖狀態是下面的哪種????

hash

Age

是否偏向鎖:1

鎖標識位:01

null

epoch

age

是否偏向鎖:1

鎖標識位:01

重新偏向執行緒2

執行緒2ID

age

是否偏向鎖:1

鎖標識位:01

4、如果原來的執行緒依然存活,則馬上執行那個執行緒的操作棧,檢查該物件的使用情況,如果仍然需要持有偏向鎖,則偏向鎖升級為輕量級鎖(偏向鎖就是這個時候升級為輕量級鎖的)。

先標記為非偏向模式

Hash

age

是否偏向鎖:0

鎖標識位:01

再進行輕量級鎖升級

Lock record 地址

鎖標識位:00

此後物件再也回不到偏向鎖模式

5、如果不存在使用了,則可以將物件回覆成無鎖狀態,然後重新偏向。

設定成無鎖狀態。????無鎖狀態是下面的哪種????

hash

Age

是否偏向鎖:1

鎖標識位:01

null

epoch

age

是否偏向鎖:1

鎖標識位:01