1. LockSupport類
AQS架構使用LockSupport來實現線程的休眠,時間性休眠,喚醒...
2. AQS架構-所有同步器的基本架構
----- a. 基於AQS架構的同步器基本上只需要實現四個函數
1. tryAcqurie(int) -- 線程會調用這個函數來做能否互斥的獲取同步器資源的嘗試的邏輯
2. tryRelease(int) -- 線程會調用這個函數來做能否互斥的釋放同步器資源的嘗試的邏輯
3. tryAcqurieShared(int) -- 線程會調用這個函數來做能否共享的獲取同步器資源的嘗試的邏輯
4. tryReleaseShared(int) -- 線程會調用這個函數來做能否共享的釋放同步器資源的嘗試的邏輯
----- b. 基於AQS架構同步器分爲
互斥同步器 例如ReentrantLock
共享同步器 例如Semaphore
互斥和共享共存的同步器ReentrantReadWriteLock
接下來會有文章依次介紹這些同步器的實現
----- c. AQS數據結構
1. 對於首次進入時獲取資源失敗的Thread,會將其封裝到一個NODE數據塊裏面
2. 會維護兩個NODE引用,分別指向NODE雙向鏈表的頭和尾,這樣來實現FIFO
3. 對於同步器所擁有的資源就是使用一個INT來表示,這也就是互斥和共享共存的
同步器同時共享的線程只能是2個BYTE能表示的長度的原因,所有又推出了一個LONG型的AQS架構
----- d. AQS核心代碼
1. acquireQueued() 實現了線程不可中斷模式下的互斥獲取資源
其主要邏輯是一個死循環
a. 線程所屬的NODE->prev是HEAD纔會調用tryAcqurie執行嘗試獲取鎖的邏輯
b. 如果嘗試獲取鎖成功則head=NODE,以及一個釋放HARD REFERENCE的操作
c. 返回線程在WAIT期間是否被標記中斷 ---> 線程擺脫同步器的控制
d. 對tryAcqurie嘗試失敗後是否需要WAIT做出判斷 ---- 重點處
1. 如果前一個NODE處於WAIT則它一定要WAIT
2. 如果前一個NODE處於CANCEL則做一個鏈表的刪除工作
3. 如果前一個NODE是最後加入的則將其標記爲WAIT
4. 2和3會讓線程再做一次嘗試,不會阻塞線程
e. 如果線程需要阻塞則調用LockSupport.park阻塞,兩種方式會讓線程醒來
1. 線程被標記中斷
2. 別的線程用LockSupport.unpark了它,有線程釋放了互斥資源
f. 線程醒來循環到a
g. 程序的邏輯就是一個嘗試獲取資源,線程阻塞,被喚醒的輪迴
2. doAcquireInterruptibly()實現了線程可中斷模式下的互斥獲取資源
其原理和acquireQueued()一樣,不同之處是線程在被中斷後即在1.e.1條件下會直接退出死循環
3. doAcquireNanos()實現了線程可中斷+記時模式下的互斥獲取資源
a. 在阻塞前會先計算阻塞的時間,進入休眠
b. 如果被中斷則會判斷時間是否到了
1. 如果沒到則且被其他線程設置了中斷標誌,退出那個輪迴,拋出中斷異常,如果沒有被設置中斷標記則是前一個線程
釋放了資源再喚醒了它,其繼續走那個輪迴,輪迴中,如果tryAcquire成功則擺脫了同步器的控制,否則回到a
2. 如果時間到了則退出輪迴,獲取資源失敗
4. release()實現了互斥資源的釋放,最主要的工作就是將其下一個線程喚醒1.e.2
5. doAcquireShared()實現了線程不可中斷模式下的共享獲取資源
a. 線程所屬的NODE->prev是HEAD纔會調用tryAcquireShared執行嘗試獲取鎖的邏輯
b. 如果嘗試獲取鎖成功則head=NODE,以及一個釋放HARD REFERENCE的操作
此處和互斥的明顯區別是,線程在獲取成功後如果還有剩餘的資源會喚醒其後的線程
也就是如果其下一個線程也是共享的獲取資源,其被喚醒的理由多了個
c. 線程在WAIT期間是否被標記中斷則標記,因爲這期間的標記狀態會被清掉 ---> 線程擺脫同步器的控制
d. 對tryAcquireShared嘗試失敗後是否需要WAIT做出判斷 ---- 重點處
1. 如果前一個NODE處於WAIT則它一定要WAIT
2. 如果前一個NODE處於CANCEL則做一個鏈表的刪除工作
3. 如果前一個NODE是最後加入的則將其標記爲WAIT
4. 2和3會讓線程再做一次嘗試,不會阻塞線程
e. 如果線程需要阻塞則調用LockSupport.park阻塞,三種方式會讓線程醒來
1. 線程被標記中斷
2. 別的線程釋放了資源LockSupport.unpark了它
3. 其前一個共享線程醒了以後獲取了資源而其還有資源也會喚醒它
f. 線程醒來循環到a
g. 程序的邏輯就是一個嘗試獲取資源,線程阻塞,被喚醒的輪迴
6. doAcquireSharedInterruptibly()實現了線程可中斷模式下的共享獲取資源
其原理和doAcquireShared()一樣,不同之處是線程在被中斷後即在5.e.1條件下會直接退出死循環
7. doAcquireSharedNanos()實現了線程可中斷+記時模式下的共享獲取資源
a. 在阻塞前會先計算阻塞的時間,進入休眠
b. 如果被中斷則會判斷時間是否到了
1. 如果沒到則且被其他線程設置了中斷標誌,退出那個輪迴,拋出中斷異常,如果沒有被設置中斷標記則是前一個線程
釋放了資源再喚醒了它,其繼續走那個輪迴,輪迴中,如果tryAcquire成功則擺脫了同步器的控制,否則回到a
2. 如果時間到了則退出輪迴,獲取資源失敗
8. releaseShared()和release()一樣