jdk1.6中為了減少獲取鎖和得到鎖帶來的性能消耗,引入了偏向鎖和輕量級鎖,再java1.6中,鎖有四種狀態,
- 無鎖
- 偏向鎖
- 輕量級鎖
- 重量級鎖

偏向鎖(只適用于一個執行緒訪問的情景)
其實鎖是不存在多執行緒競爭的,且總是由同一執行緒多次獲得,為了讓執行緒獲得鎖的代價更低,引入了偏向鎖,當一個執行緒訪問同步代碼塊并獲取鎖時,會在物件頭和堆疊幀中鎖記錄中記錄偏向鎖的執行緒id, 當以后該執行緒再進入同步代碼塊的時候,只需要簡單的測驗物件頭里面的Mark Word的存盤結構是否存盤著指向當前執行緒的偏向鎖,如果,測驗成功,那么久表示獲得了鎖,如果測驗失敗,那么就需要測驗一下偏向鎖的標識是否設定了1,如果是1則嘗試使用CAS將物件頭的偏向鎖指向當前執行緒,如果不是1則使用CAS競爭鎖,
偏向鎖使用了競爭出現才釋放鎖的機制,當其他執行緒嘗試晶振偏向鎖時持有偏向鎖的執行緒菜會釋放鎖,而且需要等待全域安全點,安全點指的是,在這個時間點上沒有正在執行的位元組碼,撤銷的時候先檢查持有偏向鎖的執行緒是否還活著,如果執行緒不處于活動狀態,則將物件頭設定為成無鎖狀態,如果執行緒仍然活著,擁有偏向鎖的堆疊會被執行,遍歷偏向物件的鎖記錄,堆疊中的鎖記錄和物件頭的Mark Word要么重新偏向其他執行緒,要么恢復到無所或標記物件不適合作為偏向鎖,最后喚醒,

輕量級鎖
加鎖:
執行緒在執行同步塊之前,JVM會先在當前執行緒的堆疊楨中創建用于存盤鎖記錄的空間,并將物件頭中的Mark Word復制到鎖記錄中,官方稱為Displaced Mark Word,然后執行緒嘗試使用CAS將物件頭中的Mark Word替換為指向鎖記錄的指標,如果成功,當前執行緒獲得鎖,如果失敗,表示其他執行緒競爭鎖,當前執行緒便嘗試使用自旋來獲取鎖,
解鎖:
輕量級解鎖時,會使用原子的CAS操作將Displaced Mark Word替換回到物件頭,如果成
功,則表示沒有競爭發生,如果失敗,表示當前鎖存在競爭,鎖就會膨脹成重量級鎖,圖2-2是
兩個執行緒同時爭奪鎖,導致鎖膨脹的流程圖,
偏向鎖:加鎖和解鎖不需要額外的消耗,但是執行緒之間存在鎖競爭,鎖撤銷的時候消耗要大,
輕量級鎖:競爭的執行緒不會阻塞,提高了執行緒的回應速度,如果始終得不到鎖,那么就會自旋消耗cpu, 目的是為了追求相應時間,
重量級鎖:不會使用自旋,不消耗cpu,執行緒阻塞,回應慢,但是追求吞吐量,
參考java編程之美 ,記錄本文是為了加深自己對并發的鎖的印象
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/279544.html
標籤:其他
下一篇:java并發編程之Lock鎖
