reentrantlock內部有公平鎖和非公平鎖兩種,而這兩種鎖都是基於aqs同步器實現的。aqs同步器太難看懂,先簡單看下reentrantlock的原始碼,再反推回去看aqs。
1、公平鎖能保證:老的執行緒排隊使用鎖,新執行緒仍然排隊使用鎖。
2、非公平鎖保證:老的執行緒排隊使用鎖;但是無法保證新執行緒搶占已經在排隊的執行緒的鎖。
在公平鎖中,每一次的tryacquire都會檢查clh佇列中是否仍有前驅的元素,如果仍然有那麼繼續等待,通過這種方式來保證先來先服務的原則。
而非公平鎖,首先是檢查並設定鎖的狀態,這種方式會出現即使佇列中有等待的執行緒,但是新的執行緒仍然會與排隊執行緒中的對頭執行緒競爭(但是排隊的執行緒是先來先服務的),所以新的執行緒可能會搶占已經在排隊的執行緒的鎖,這樣就無法保證先來先服務,但是已經等待的執行緒們是仍然保證先來先服務。
預設建構函式:
預設就是使用的非公平鎖(估計是因為非公平鎖效率高吧)。
非公平鎖加鎖:lock()
首先使用cas的方式將state設定為1,1
代表當前
執行緒獲取了一次
鎖,並將當前執行緒設定為獨佔。也就是說reentrantlock
內部的非公平鎖是乙個獨佔鎖。(其實從下面的tryacquire()就可以看出來它是乙個獨佔鎖,aqs同步器獨佔鎖搶占的命名就是這個)
如果狀態設定未成功,則呼叫aqs類中的acquire(1)進行鎖的強佔(aqs中詳細的怎麼執行的後續文章分析吧)。acquire(1)會首先執行自定義的鎖強佔邏輯,不成功則執行由它定義的後續邏輯。記得
內部會設定
將強佔的執行緒放到佇列裡面,這不就違反了公平的邏輯麼?
而且放到隊裡
裡面的話鎖會自旋,有沒有不自旋的方法
?看下它自定義的鎖搶占方法:nonfairtryacquire(int acquires)
我將它分成了上下兩部分:
如果當前的state=0,表示鎖被釋放了,那麼仍然通過cas的方式將自己設定進去。
如果還是當前執行緒來強佔鎖,那麼將
state+1
,這就是重入的邏輯
,側面也說明了aqs
類沒有實現
重入邏輯。
釋放鎖:unlock(),只有乙個方法,看來公平鎖和非公平鎖釋放的邏輯是一致的
呼叫的是aqs類中的釋放
獨佔鎖的邏輯,我們稍微看下aqs裡面怎麼實現的:
其實就是呼叫使用者自身定義的tryrelease()邏輯,然後再做一些收尾工作。那麼久看下自定義的釋放鎖的方法。
其實核心就這句話,lock幾次就要unlock幾次,執行緒不在占有鎖就是state減到0的時候。看到
這裡還不明白的一點是非公平怎麼實現的
,這個要看
aqs了。
建構函式傳入true:
看下它加鎖的邏輯:lock()
和非公平鎖是一樣的,底層呼叫的還是aqs的邏輯,只是自定義的加鎖的方式不一樣,並且它也是實現的獨佔鎖的介面,那就是說reentrantlock中的
鎖都是獨佔鎖。
和非公平鎖唯一不同的是,它也有
queue的概念,
搶占的執行緒是放入到佇列中,每次從佇列的頭部獲取執行緒,
讓這個執行緒來
獲取鎖。至於重入的概念和非公平鎖是一致。
reentrantlock類中還有乙個newcondition()方法,但是這個好像不是給它自己本身用的,而是給
它物件用的:
可以參考我分析cyclicbarrier那篇文章,這個類中cyclicbarrier類中就是用來判斷一組物件是不是達到了某種條件,額…後面看的越多估計會理解的越深一點。
SpringMVC處理請求的大致流程是怎麼樣的
spring mvc請求處理架構圖 1 使用者首先傳送請求到前端控制器dispatcher servlet 3 接著將得到的處理器handlerexecutionchain包裝成為handleradapter 介面卡 4 根據得到的handleradapter呼叫真正的處理器得到modelandvi...
Android View類中的生命週期是怎樣的
android view有以下14個週期 1 onfinishinflate 當view中所有的子控制項均被對映成xml後觸發 2 onmeasure int int 確定所有子元素的大小 3 onlayout boolean int int int int 當view分配所有的子元素的大小和位置時...
生成器python python生成器是怎樣工作的
第一部分 在掌握python生成器之前,你需要理解普通的python函式是如何工作的。通常,當乙個python函式呼叫乙個子程式時,子程式保留控制權直到它返回,或者丟擲乙個異常。然後控制權被交還給呼叫者 父程式 def foo bar def bar pass python的標準直譯器是由c寫成的。...