JUC 併發類概覽

JUC 併發類及併發相關類概覽,持續補充...數組

  • AQS
    內部有兩個隊列,一個等待隊列(先後節點),一個條件隊列(後繼節點),實際上是經過鏈表方式實現;
    等待隊列是雙向鏈表;條件隊列是單向鏈表;條件隊列若是被喚醒,將後接到等待隊列上;
    經過內部持有的 state,加以模板模式,提供了兩種資源爭搶模式:排他、共享;而在爭搶時,又輔以公平、非公平競爭的考慮;
    排他與共享分別經過子類實現的:boolean tryAcquire(tryAcquireShared(x) >= 0 來判斷獲取資源是否成功,同時排他限制:state 只能被一個線程修改(通常修改成 1,CAS(0,1),可重入);而共享則支持多線程同時更改 state 值(被多個線程獲取);
    獲取時要考慮是否關注中斷喚醒行爲,對應方法名後綴:-Interruptible,關注則拋異常,不關注則清除線程的中斷標記位記錄,繼續掛起直到獲取成功,再中斷線程;
    總的下來,分支考慮就是:資源類型(是否排他)-> 是否公平 -> 是否關注中斷(每個都是兩個方向)
    釋放資源時,排他類型須要判斷是否當前線程,而共享類型不須要判斷線程,只關注資源池;排他類型會喚醒等待隊列的下一個節點,而共享則會經過級聯方式傳遞信號,從 head 開始喚醒,直到資源被新喚醒的線程搶光才中止;
    線程的掛起是經過 LockSupport.park(thread),支持限時掛起;
    state 釋放致使等待隊列判斷,進而喚醒。限時掛起一定支持中斷響應;
    條件隊列由於初始時是經過 new ConditionObject(),能夠屢次建立,因此支持多個條件隊列,使用同一個對象便是同一個條件隊列;被喚醒時會執行 state 的資源獲取,獲取不到則進入等待隊列;一樣支持是否中斷關注;而條件隊列的中斷有兩種狀況,一種在條件隊列上被中斷喚醒,一種是在進入等待隊列後被中斷喚醒;
    AQS 主要是資源 state 的 CAS 併發及線程中斷掛起,排隊的控制

  • AQLS
    state 的類型爲 long,擴展了併發數(將來擴展)。其餘與 AQS 相同。
    long 須要關注緩存行問題。

  • ReentrantLock
    基於 AQS 實現的鎖,設置 state = 1;支持公平與非公平(判斷隊列是否有等待線程);支持重入,state 遞增;競爭時只有 state = 0 才獲取鎖成功,不然進入等待隊列;
    支持 condition 的 await 和 signal。

  • CopyOnWriteArrayList
    與 AQS 無關,使用的 synchronized 保證同步安全;當發生添加行爲時,會將原數組拷貝一份進行添加,而後更新引用;當發生指定索引添加時,會定位索引,分兩步進行拷貝(索引前、索引後);適合讀多寫少場景;addIfAbsent 會先判斷(無同步鎖),而後拷貝(有同步鎖),判斷時會先拷貝一份快照,在更新索引時判斷快照是否最新,是則直接使用,不然從新拷貝;

  • CopyOnWriteArraySet
    底層使用了 CopyOnWriteArrayList。惟一性的添加則是使用了 addIfAbsent。其餘大部分方法直接調用了 CopyOnWriteArrayList 的相似方法;

  • CountDownLatch
    使用了 AQS,初始化大小即爲 state,每次 countDown 都是對 state - 1,而 await 則是在判斷 getState() == 0 ? 1 : -1 不經過掛起在隊列中,因此有多少 state 則其會被喚醒 state 次,而後從新掛起,直到 state = 0

  • ArrayBlockingQueue
    未直接使用或繼承 AQS,而是經過使用 ReentrantLock 和 Condition 來完成多線程同步與掛起;
    內部使用數組存儲元素,但不會擴展,實現了環形隊列存儲,隊列元素增長 offer 及獲取 poll 都使用 lock 進行同步;
    當添加成功時,進行 notEmpty.signal() 通知,喚醒獲取失敗的線程(notEmpty.await())處理;
    當獲取成功時,進行 notFull.signal() 通知,喚添加失敗的線程(notFulll.await())處理;
    offer(E) 添加返回 true/falseadd(E) 內部調用 offer,返回 false 則拋異常;put 自實現,沒法添加則阻塞;
    poll() 獲取返回 E/nulltake 自實現,若是獲取不到則阻塞掛起;
    任何添加或獲取成功,相應的都會進行 notEmptynotFull 通知,而失敗則進入相反的隊列掛起;ArrayBlockingQueue 的併發遍歷實現是經過隊列延展實現的(就是一個隊列,不斷的翻滾);相似於環形隊列
相關文章
相關標籤/搜索