Java併發面試問題之公平鎖與非公平鎖

2021-09-13 16:06:36 字數 1045 閱讀 2743

非公平鎖

注意一點,此時執行緒2可還停留在等待佇列裡啊,還沒開始嘗試重新加鎖呢!

然而,不幸的事情發生了,這時半路殺出個程咬金,來了乙個執行緒3!執行緒3突然嘗試對reentrantlock發起加鎖操作,此時會發生什麼事情?

很簡單!執行緒2還沒來得及重新嘗試加鎖呢。也就是說,還沒來得及嘗試重新執行cas操作將state的值從0變為1呢!執行緒3衝上來直接乙個cas操作,嘗試將state的值從0變為1,結果還成功了!

一旦cas操作成功,執行緒3就會將「加鎖執行緒」這個變數設定為他自己。給大家來一張圖,看看這整個過程:

明明人家執行緒2規規矩矩的排隊領鎖呢,結果你執行緒3不守規矩,執行緒1剛釋放鎖,不分青紅皂白,直接就跑過來搶先加鎖了。

這就導致執行緒2被喚醒過後,重新嘗試加鎖執行cas操作,結果毫無疑問,失敗!

原因很簡單啊!因為加鎖cas操作,是要嘗試將state從0變為1,結果此時state已經是1了,所以cas操作一定會失敗!

一旦加鎖失敗,就會導致執行緒2繼續留在等待佇列裡不斷的等著,等著執行緒3釋放鎖之後,再來喚醒自己,真是可憐!先來的執行緒2居然加不到鎖!

上述的鎖策略,就是所謂的非公平鎖!

如果你用預設的建構函式來建立reentrantlock物件,預設的鎖策略就是非公平的。

那如果要實現公平鎖的策略該怎麼辦呢?也很簡單,在構造reentrantlock物件的時候傳入乙個true即可:

reentrantlock lock = new reentrantlock(true)

什麼是公平鎖?

如果aqs的佇列裡真的有執行緒排著隊,那我執行緒3就不能跟個二愣子一樣直接搶占加鎖了。

因為現在咱們是公平策略,得按照先來後到的順序依次排隊,誰先入隊,誰就先從佇列裡出來加鎖!

所以,執行緒3此時一判斷,發現佇列裡有人排隊,自己就會乖乖的排到佇列後面去,而不會貿然加鎖!

Java併發之公平鎖

cpu在排程執行緒的時候,會在等待佇列裡隨機挑選乙個執行緒。由於隨機性,故不能保證執行緒先到先得 synchronized控制的鎖就是這種非公平鎖 這樣就會產生飢餓現象,即有些優先順序較低的執行緒可能永遠無法取得cpu的執行權,優先順序較高的執行緒會不斷搶占資源。於是,就有了公平鎖。公平鎖可以保證執...

美團點評java開發面試問題

1.介紹上家公司的職責與專案等,說乙個最熟悉的專案中自己認為的亮點 2.線上出現過什麼問題,怎麼解決的 3.redis鎖原理,系統qps值多少,快取穿透與雪崩,redis更新失敗的解決方案,redis資料型別,底層資料結構,redis快取優化舉例,持久化,基本命令 4.有沒有使用過rpc框架,講講 ...

java並發包中的公平鎖與非公平鎖有啥區別

注意一點,此時執行緒2可還停留在等待佇列裡啊,還沒開始嘗試重新加鎖呢!然而,不幸的事情發生了,這時半路殺出個程咬金,來了乙個執行緒3!執行緒3突然嘗試對reentrantlock發起加鎖操作,此時會發生什麼事情?很簡單!執行緒2還沒來得及重新嘗試加鎖呢。也就是說,還沒來得及嘗試重新執行cas操作將s...