輕量級鎖,偏向鎖,重量級鎖

2022-06-20 10:30:13 字數 3353 閱讀 2974

物件頭資訊:

使用monitor物件來實現重量級鎖,如果使用重量級鎖,加鎖過程就需要先去關聯monitor物件,然後還需要各種判斷。

asychronized關鍵字實現重量級鎖的原理:

monitorenter和monitorexit就是操作monitor物件,會有效能損耗,所以引入輕量級鎖。

當出現重量級鎖競爭的時候,不會馬上進入阻塞,阻塞會進入上下文切換,會影響效能的,而是先使用自旋重試,自旋只有多核cpu才有意義,乙個核進行資源訪問,另乙個核進行嘗試加鎖,如果是乙個核,這個核在訪問資源,那也沒必要花時間去重試,所以自旋必然是多核cpu才有意義。jvm會自動控制自旋重試次數,只有多核才有意義。

利用執行緒棧中的鎖標記來加鎖。加鎖過程只是替換物件頭資訊即可,這比重量級鎖使用monitor來說效能會有提公升,這就是對重量級鎖的優化。

輕量級鎖的加鎖過程也就是交換執行緒棧和物件頭資訊即可,這樣就會優化monitor了。

不管加鎖成功與否,都會執行一次cas操作。

鎖重入:乙個執行緒對同乙個物件多次加鎖

雖然多執行緒會對乙個資源進行加鎖,但是如果這些執行緒訪問是錯開的,也就是這些執行緒不會競爭資源,這時候使用輕量級鎖能提高效能,畢竟沒有引入monitor物件,只是進行cas操作,這是輕量級鎖引入的原因。執行緒之間不會競爭,如果出現競爭,依然會使用重量級鎖,所以輕量級鎖就是用來優化重量級鎖效能問題的。

輕量級鎖在沒有競爭時,每次重入仍然需要執行cas操作,cas也會影響效能,所以引入偏向鎖。

注意到偏向鎖的物件頭,裡面有執行緒id,所以偏向鎖會減少cas操作,在一定程度上優化輕量級鎖.

jvm預設是開啟偏向鎖的,但不會在程式啟動時就生效,而是有一點延遲,可以加vm引數-xx:biasedlockingstartupdelay=0來禁用延遲,使用asychronized加鎖,會優先使用偏向鎖。

vm引數 -xx:-usebiasedlocking 禁用偏向鎖,-xx:+usebiasedlocking 使用偏向鎖。

物件呼叫hashcode()方法會禁用該物件的偏向鎖,原因就是呼叫了hashcode()方法,物件頭就沒有地方存放執行緒id了,只能禁用該物件的偏向鎖。重量級鎖在monitor物件中儲存hashcode。

當兩個及以上執行緒使用同乙個物件時,偏向鎖將會公升級為輕量級鎖,如果這些執行緒會產生資源競爭,則進一步公升級為重量級鎖。

物件呼叫wait/notify,也會撤銷物件的偏向狀態,原因是只有重量級鎖才會有wait/notify機制

連續撤銷偏向超過40次(超過閾值),jvm會認為確實偏向錯了,於是所有類都不可偏向,新建的物件也不可以偏向

當撤銷偏向超過20次後(超過閾值),jvm 會覺得是不是偏向錯了,這時會在給物件加鎖時,又會重新開始偏向。

vectorlist = new vector<>();

thread t1 = new thread(() ->

}synchronized (list)

}, "t1");

t1.start();

thread t2 = new thread(() -> catch (interruptedexception e)

}log.debug("***************> ");

for (int i = 0; i < 30; i++)

log.debug(i + "\t" + classlayout.parseinstance(d).toprintable()); // 前20個處於無偏向狀態,兩個執行緒使用,撤銷偏向,後面的10個會偏向t2

// 後面的10個偏向t2,就是因為jvm發現撤銷偏向超過20次後(超過閾值),重新的批量偏向另乙個執行緒

}}, "t2");

t2.start();

-xx:-eliminatelocks,關閉鎖消除

-xx:+eliminatelocks,開啟鎖消除,預設開啟

對於 synchronized 鎖來說,鎖的公升級主要是通過 mark word 中的鎖標記位與是否是偏向鎖標記為來達成的;synchronized 關鍵字所物件的鎖都是先從偏向鎖開始,隨著鎖競爭的不斷公升級,逐步演化至輕量級鎖,最後變成了重量級鎖。

偏向鎖:針對乙個執行緒來說的,主要作用是優化同乙個執行緒多次獲取乙個鎖的情況, 當乙個執行緒執行了乙個 synchronized 方法的時候,肯定能得到物件的 monitor ,這個方法所在的物件就會在 mark work 處設為偏向鎖標記,還會有乙個字段指向擁有鎖的這個執行緒的執行緒 id 。當這個執行緒再次訪問同乙個 synchronized 方法的時候,如果按照通常的方法,這個執行緒還是要嘗試獲取這個物件的 monitor ,再執行這個 synchronized 方法。但是由於 mark word 的存在,當第二個執行緒再次來訪問的時候,就會檢查這個物件的 mark word 的偏向鎖標記,再判斷一下這個字段記錄的執行緒 id 是不是跟第二個執行緒的 id 是否相同的。如果相同,就無需再獲取 monitor 了,直接進入方法體中。

如果是另乙個執行緒訪問這個 synchronized 方法,那麼實際情況會如何呢?:偏向鎖會被取消掉。

輕量級鎖:若第乙個執行緒已經獲取到了當前物件的鎖,這是第二個執行緒又開始嘗試爭搶該物件的鎖,由於該物件的鎖已經被第乙個執行緒獲取到,因此它是偏向鎖,而第二個執行緒再爭搶時,會發現該物件頭中的 mark word 已經是偏向鎖,但裡面儲存的執行緒 id 並不是自己(是第乙個執行緒),那麼她會進行 cas(compare and swap),從而獲取到鎖,這裡面存在兩種情況:

旋鎖,若自旋失敗,那麼鎖就會轉化為重量級鎖,在這種情況下,無法獲取到鎖的執行緒都會進入到 moniter(即核心態),自旋最大的特點是避免了執行緒從使用者態進入到核心態。

偏向鎖 輕量級鎖 重量級鎖

首先簡單說下先偏向鎖 輕量級鎖 重量級鎖三者各自的應用場景 偏向鎖 只有乙個執行緒進入臨界區 輕量級鎖 多個執行緒交替進入臨界區 重量級鎖 多個執行緒同時進入臨界區。還要明確的是,偏向鎖 輕量級鎖都是jvm引入的鎖優化手段,目的是降低執行緒同步的開銷。比如以下的同步 塊 synchronized l...

偏向鎖 輕量級鎖 重量級鎖

synchronized關鍵字就像是汽車的自動檔,現在詳細講這個過程。一腳油門踩下去,synchronized會從無鎖公升級為偏向鎖,再公升級為輕量級鎖,最後公升級為重量級鎖,就像自動換擋一樣。那麼自旋鎖在 呢?這裡的輕量級鎖就是一種自旋鎖。初次執行到synchronized 塊的時候,鎖物件變成偏...

偏向鎖,輕量級鎖,重量級鎖(java)

輕量級鎖是jdk 1.6之中加入的新型鎖機制,它名字中的 輕量級 是相對於使用作業系統互斥量來實現的傳統鎖而言的,因此傳統的鎖機制就稱為 重量級 鎖。首先需要強調一點的是,輕量級鎖並不是用來代替重量級鎖的,它的本意是在沒有多執行緒競爭的前提下,減少傳統的重量級鎖使用作業系統互斥量產生的效能消耗。要理...