歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)
java
週一至週五早8點半!精品技術文章準時送上!面試
上篇文章(大白話聊聊Java併發面試問題之談談你對AQS的理解?)聊了一下java併發包中的AQS的工做原理,也間接說明了ReentrantLock的工做原理。算法
這篇文章接着來聊一個話題,java併發包中的公平鎖與非公平鎖有啥區別?性能優化
先來聊聊非公平鎖是啥,如今你們先回過頭來看下面這張圖。架構
如上圖,如今線程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)
此時就是說讓他使用公平鎖的策略,那麼公平鎖具體是什麼意思呢?
我們從新回到第一張圖,就是線程1剛剛釋放鎖以後,線程2還沒來得及從新加鎖的那個狀態。
一樣,這時假設來了一個線程3,忽然殺出來,想要加鎖。
若是是公平鎖的策略,那麼此時線程3不會跟個愣頭青同樣盲目的直接加鎖。
他會先判斷一下:咦?AQS的等待隊列裏,有沒有人在排隊啊?若是有人在排隊的話,說明我前面有兄弟正想要加鎖啊!
若是AQS的隊列裏真的有線程排着隊,那我線程3就不能跟個二愣子同樣直接搶佔加鎖了。
由於如今我們是公平策略,得按照先來後到的順序依次排隊,誰先入隊,誰就先從隊列裏出來加鎖!
因此,線程3此時一判斷,發現隊列裏有人排隊,本身就會乖乖的排到隊列後面去,而不會貿然加鎖!
一樣,整個過程咱們用下面這張圖給你們直觀的展現一下:
上面的等待隊列中,線程3會按照公平原則直接進入隊列尾部進行排隊。
接着,線程2不是被喚醒了麼?他就會從新嘗試進行CAS加鎖,此時沒人跟他搶,他固然能夠加鎖成功了。
而後呢,線程2就會將state值變爲1,同時設置「加鎖線程」是本身。最後,線程2本身從等待隊列裏出隊。
整個過程,參見下圖:
這個就是公平鎖的策略,過來加鎖的線程所有是按照先來後到的順序,依次進入等待隊列中排隊的,不會盲目的胡亂搶佔加鎖,很是的公平。
好了,經過畫圖和文字分析,相信你們都明白什麼是公平鎖,什麼是非公平鎖了!
不過要知道java併發包裏不少鎖默認的策略都是非公平的,也就是可能後來的線程先加鎖,先來的線程後加鎖。
而通常狀況下,非公平的策略都沒什麼大問題,可是你們要對這個策略作到內心有數,在開發的時候,須要本身來考慮和權衡是要用公平策略仍是非公平策略。
併發系列文章 ,正在更新中,歡迎關注:
大白話聊聊Java併發面試問題之volatile究竟是什麼?
大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?
大白話聊聊Java併發面試問題之談談你對AQS的理解?
《大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?》
《大白話聊聊Java併發面試問題之微服務註冊中心的讀寫鎖優化?》 ,敬請期待
若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!
一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上
歡迎掃描下方二維碼,持續關注:
石杉的架構筆記(id:shishan100)
十餘年BAT架構經驗傾囊相授
推薦閱讀:二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?
三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰
六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問
七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍
八、拜託,面試請不要再問我TCC分佈式事務的實現原理坑爹呀!
九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?
十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?
1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構
1八、大白話聊聊Java併發面試問題之volatile究竟是什麼?