大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?【石杉的架構筆記】

歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)
java

週一至週五早8點半!精品技術文章準時送上!面試

1、寫在前面

上篇文章(大白話聊聊Java併發面試問題之談談你對AQS的理解?)聊了一下java併發包中的AQS的工做原理,也間接說明了ReentrantLock的工做原理。算法

這篇文章接着來聊一個話題,java併發包中的公平鎖與非公平鎖有啥區別?性能優化


2、什麼是非公平鎖?

先來聊聊非公平鎖是啥,如今你們先回過頭來看下面這張圖。架構

如上圖,如今線程1加了鎖,而後線程2嘗試加鎖,失敗後進入了等待隊列,處於阻塞中。而後線程1釋放了鎖,準備來喚醒線程2從新嘗試加鎖。併發

注意一點,此時線程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竟然加不到鎖!

一樣給你們來一張圖,體會一下線程2這無助的過程:


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

若是你用默認的構造函數來建立ReentrantLock對象,默認的鎖策略就是非公平的。

在非公平鎖策略之下,不必定說先來排隊的線程就就先會獲得機會加鎖,而是出現各類線程隨意搶佔的狀況。

那若是要實現公平鎖的策略該怎麼辦呢?也很簡單,在構造ReentrantLock對象的時候傳入一個true便可:

ReentrantLock lock = new ReentrantLock(true)

此時就是說讓他使用公平鎖的策略,那麼公平鎖具體是什麼意思呢?


3、什麼是公平鎖?

我們從新回到第一張圖,就是線程1剛剛釋放鎖以後,線程2還沒來得及從新加鎖的那個狀態。


一樣,這時假設來了一個線程3,忽然殺出來,想要加鎖。

若是是公平鎖的策略,那麼此時線程3不會跟個愣頭青同樣盲目的直接加鎖。

他會先判斷一下:咦?AQS的等待隊列裏,有沒有人在排隊啊?若是有人在排隊的話,說明我前面有兄弟正想要加鎖啊!

若是AQS的隊列裏真的有線程排着隊,那我線程3就不能跟個二愣子同樣直接搶佔加鎖了。

由於如今我們是公平策略,得按照先來後到的順序依次排隊,誰先入隊,誰就先從隊列裏出來加鎖!

因此,線程3此時一判斷,發現隊列裏有人排隊,本身就會乖乖的排到隊列後面去,而不會貿然加鎖!

一樣,整個過程咱們用下面這張圖給你們直觀的展現一下:


上面的等待隊列中,線程3會按照公平原則直接進入隊列尾部進行排隊。

接着,線程2不是被喚醒了麼?他就會從新嘗試進行CAS加鎖,此時沒人跟他搶,他固然能夠加鎖成功了。

而後呢,線程2就會將state值變爲1,同時設置「加鎖線程」是本身。最後,線程2本身從等待隊列裏出隊。

整個過程,參見下圖:


這個就是公平鎖的策略,過來加鎖的線程所有是按照先來後到的順序,依次進入等待隊列中排隊的,不會盲目的胡亂搶佔加鎖,很是的公平。


4、小結

好了,經過畫圖和文字分析,相信你們都明白什麼是公平鎖,什麼是非公平鎖了!

不過要知道java併發包裏不少鎖默認的策略都是非公平的,也就是可能後來的線程先加鎖,先來的線程後加鎖。

而通常狀況下,非公平的策略都沒什麼大問題,可是你們要對這個策略作到內心有數,在開發的時候,須要本身來考慮和權衡是要用公平策略仍是非公平策略。


併發系列文章 ,正在更新中,歡迎關注:
大白話聊聊Java併發面試問題之volatile究竟是什麼?
大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?
大白話聊聊Java併發面試問題之談談你對AQS的理解?
《大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?》
《大白話聊聊Java併發面試問題之微服務註冊中心的讀寫鎖優化?》 敬請期待


END


若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!


一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上

歡迎掃描下方二維碼,持續關注:


石杉的架構筆記(id:shishan100)

十餘年BAT架構經驗傾囊相授


推薦閱讀:

一、拜託!面試請不要再問我Spring Cloud底層原理

二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?

三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰

四、微服務架構如何保障雙11狂歡下的99.99%高可用

五、兄弟,用大白話告訴你小白都能聽懂的Hadoop架構原理

六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問

七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍

八、拜託,面試請不要再問我TCC分佈式事務的實現原理坑爹呀!

九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?

十、拜託,面試請不要再問我Redis分佈式鎖的實現原理!

十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?

十二、億級流量系統架構之如何支撐百億級數據的存儲與計算

1三、億級流量系統架構之如何設計高容錯分佈式計算系統

1四、億級流量系統架構之如何設計承載百億流量的高性能架構

1五、億級流量系統架構之如何設計每秒十萬查詢的高併發架構

1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構

1七、七張圖完全講清楚ZooKeeper分佈式鎖的實現原理

1八、大白話聊聊Java併發面試問題之volatile究竟是什麼?

1九、大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?

20、大白話聊聊Java併發面試問題之談談你對AQS的理解?

相關文章
相關標籤/搜索