當前物件型別
物件頭長度
陣列3字長
非陣列2字長
長度內容
說明1個字長(32bit/64bit)
mark world
儲存物件的hashcode以及鎖的資訊
1個字長
class metedata address
儲存物件型別資料的指標
1個字長
array length
陣列長度(如果物件是陣列)
鎖狀態25bit
4bit
1bit偏向鎖標誌位
2bit鎖標誌位
無鎖hashcode
物件分代年齡001
鎖狀態30bit
2bit鎖標誌位
輕量級鎖
指向執行緒棧中鎖記錄的指標00
鎖狀態30bit
2bit鎖標誌位
重量級鎖
指向互斥量(重量級鎖)的指標10
鎖狀態30bit
2bit鎖標誌位
gc標記空11
鎖狀態23bit
2bit
1bit偏向鎖標誌位
2bit鎖標誌位
偏向鎖線程id
epoch101
加鎖 偏向鎖的撤銷加鎖
釋放鎖經過輕量級鎖變化得到的重量級鎖。轉化為重量級鎖的前提是:多個執行緒存在競爭鎖。
鎖型別優點
缺點適用場景
偏向鎖加鎖解鎖不需要額外消耗,和執行非同步方法差不多
如果存在鎖競爭,會帶來額外鎖撤銷的消耗
只有乙個執行緒訪問同步塊
輕量級鎖
競爭的執行緒不會阻塞,提高了程式的響應速度
得不到鎖競爭的執行緒,自旋消耗cpu
追求響應時間,同步塊執行速度非常快
重量級鎖
執行緒不使用自旋,不消耗cpu
執行緒阻塞,響應時間緩慢
追求吞吐量,同步塊執行速度較長
如果記憶體中的a值和你認為的a值一致,即在當前執行緒對a變數進行修改時,沒有其他執行緒對a進行過修改,當前修改操作成功,返回成功。
if current_a == expected_a:
current_a = altered_a
return true
如果值不一致,即當前執行緒對a變數進行修改時,有其他執行緒對a變數進行修改過,當前修改操作終止,返回失敗。
else
return false
aba問題兩個執行緒進行同步操作,執行緒1獲取到共享變數v的值為a,然後此時執行緒2對共享變數v進行操作將它改為b,然後又改為了a,此時執行緒1進行cas操作發現v的值還是a,認為這段時間沒有執行緒對v進行操作,然後執行對v的操作。這聽上去沒有什麼問題,然而實際應用中會帶來意想不到的問題。發生原因
這個問題存在的根本原因是cas只對值進行判斷,會丟失某些執行緒對變數的操作。
場景只要當前賬戶餘額小於100元的,免費發50元。
解決加版本號,對每個變數不僅僅記錄他的值,而且記錄發生時的版本(比如通過新增乙個flag,來標記是否被處理過,或者記錄時間等資訊),將這兩個值作為乙個整體,讓cas進行判斷。
這樣每次比對時不只是比對值,還比對版本號,就不會發生aba問題了。
典型實現
類似的處理還有資料庫中對資料行的操作也可以採用加版本號來解決。
迴圈時間長開銷大
如果迴圈cas操作一直不成功,會給cpu帶來很大開銷。
只能保證乙個共享變數的原子操作
解決將多個共享變數合併成乙個共享變數來操作,
典型實現
讀寫鎖中,將讀狀態和寫狀態放在乙個變數中,低16位表示寫狀態,高16位表示讀狀態。
併發程式設計雜篇
atomically adds the given value to the current value.param delta the value to add return the updated value public final intaddandget int delta public ...
併發程式設計 執行緒篇
public class shutdown private static class runner implements runnable system.out.println count i i public void cancel 本質 對乙個物件的監視器 monitor 進行獲取,而這個獲取過...
併發程式設計基礎
從本質上來說,作業系統其實就是人為編寫的一種軟體,只不過它是一種操作計算機系統的軟體,所有的應用型軟體幾乎都要通過作業系統才能執行來執行功能,沒有不依靠作業系統就能執行功能的應用軟體 除非你真的很厲害,能夠自己操作相應的儲存器 cpu等硬體來提 用軟體的執行條件 一方面,它為應用軟體和使用者提供了操...