J.U.C 之AQS

J.U.C 之AQS

AbstractQueuedSynchronizer - AQS

image

實現(xiàn)原理

  • 使用Node實現(xiàn)FIFO隊列,可以用于構(gòu)建鎖獲者其他同步裝置的基礎(chǔ)框架
  • 利用了一個int類型表示狀態(tài)
  • 使用方法是繼承
  • 子類通過繼承并通過實現(xiàn)它的方法管理其狀態(tài){acquire和release}的方法操縱狀態(tài)
  • 可以同時實現(xiàn)排它鎖和共享鎖模式(獨占、共享)

AQS同步組件

  • CountDownLatch - 閉鎖 (通過計數(shù)來保證線程是否一直阻塞)
  • Semaphore(可以控制同一時間并發(fā)線程的數(shù)目)
  • CyclicBarrier(和CountDownLatch類似)
  • ReetrantLock
  • Condition
  • FutureTask

CountDownLatch

介紹

  • 主要功能同步輔助類,可以阻塞當前線程的功能,簡單來說就是一個線程或多個線程一直等待,直到其他線程執(zhí)行的操作完成(通過原子操作的計數(shù)器來實現(xiàn))

應(yīng)用場景

  • 并行計算

方法

  • CountDown(int count)構(gòu)造器:給定當前執(zhí)行的線程數(shù)量
  • countdown方法:如果當前計數(shù)大于零,則遞減。 如果新計數(shù)為零,則重新啟用所有等待線程以進行線程調(diào)度。
  • await()/await(int,timeType)方法:如果當前計數(shù)為零,則此方法立即返回,確保線程執(zhí)行完畢或者線程在給定時間內(nèi)執(zhí)行完畢

Semapthore

  • 信號量控制,可以通過同步機制來控制某個資源可被同時訪問的個數(shù)
  • acquire() :獲取一個許可,如果沒有就等待
  • release():操作完成后釋放一個許可
  • tryAcquire()/tryAcquire(int):嘗試獲取一個許可,或者多個許可
  • tryAcquire(long,timeType):嘗試獲取不超過某個時間下的許可(一秒內(nèi)許可)
  • tryAcquire(int permit,long,timeType):獲取該時間內(nèi)的許可次數(shù)
    • 數(shù)據(jù)庫并發(fā)連接數(shù)控制

ConditionCyclicBarrier

  • 和CountDownLatch的區(qū)別
    • CountDownLatch計數(shù)器只能使用一次,CyclicBarrier可以使用使用reset方法重置,循環(huán)使用
    • CountDownLatch主要是實現(xiàn)或者等待其他線程完成某項操作之后,才能往下執(zhí)行,描述的是一個獲n個線程等待其他線程的關(guān)系;而CyclicBarrier是實現(xiàn)多個線程相互等待,知道所有線程都滿足了之后才能執(zhí)行后續(xù)的操作,描述的是各個線程之間相互等待的關(guān)系

ReentrantLock 與 鎖

  • ReentrantLock (可重入鎖)和synchronized 區(qū)別
    • 可重入性(基本一直)
    • 鎖的實現(xiàn)
      • synchronized是基于jvm實現(xiàn)的,ReentrantLock是jdk實現(xiàn)(簡單來說就是操作系統(tǒng)和自己寫代碼的區(qū)別)
    • 性能區(qū)別(現(xiàn)在性能差不多,syn后來采用cas優(yōu)化)
    • 功能功能
      • syn自動加鎖和釋放鎖,reentrantLock自己手動加鎖和釋放鎖
    • ReentrantLock獨有功能
      • 可指定是公平鎖還是非公平鎖(syn只能指定非公平鎖,公平鎖指先獲得鎖先執(zhí)行,后獲得所后執(zhí)行)
      • 提供了一個Condition類,可以分組喚醒需要喚醒的線程
      • 提供能夠中斷等待鎖的線程的機制,通過lock.lockInterruptibly()實現(xiàn)(通過循環(huán)調(diào)用CAS來加鎖實現(xiàn))
  • api
    • tryLock():只有在調(diào)用時沒有被另一個線程持有時才獲取鎖
    • tryLock(long,timeType):如果在給定時間內(nèi)沒有被另一個線程持有且當前線程沒有被中斷,則獲取鎖
    • lockInterruptibly(): 如果當前線程沒有被中斷,那么就獲取當前鎖,如果已經(jīng)中斷則拋出異常
    • isLocked():查詢此鎖是否由任何線程持有。此方法設(shè)計用于監(jiān)視系統(tǒng)狀態(tài),不用于同步控制
    • isHeldByCurrentThread():查詢當前線程是否保持鎖定狀態(tài)
    • hasQueuedThread(Thread):查詢是否有線程在等待獲取此鎖(監(jiān)控中使用)
    • hasQueuedThreads():查詢是否有任意的線程正在等待獲取此鎖(監(jiān)控中使用)
    • getHoldCount():查詢當前線程被此鎖鎖定的數(shù)量(也就是調(diào)用lock方法的個數(shù))

ReentrantReadWriteLock

  • 在沒有任何讀寫鎖的時候才可以取得寫入鎖
  • 悲觀讀取 (在寫入鎖執(zhí)行的時候不能有讀鎖在執(zhí)行),讀多寫少的情況下,寫鎖會產(chǎn)生饑餓

StampedLock (java 8)

  • 寫、讀、樂觀讀

  • StampedLock是java8在java.util.concurrent.locks新增的一個API。

    • ReentrantReadWriteLock 在沒有任何讀寫鎖時,才可以取得寫入鎖,這可用于實現(xiàn)了悲觀讀取。然而,如果讀取很多,寫入很少的情況下,使用 ReentrantReadWriteLock 可能會使寫程遭遇饑餓問題,也就是寫入線程無法競爭到鎖定而一直處于等待狀態(tài)。
      ? StampedLock有三種模式的鎖,用于控制讀取/寫入訪問。StampedLock的狀態(tài)由版本和模式組成。鎖獲取操作返回一個用于展示和訪問鎖狀態(tài)的票據(jù)(stamp)變量,它用相應(yīng)的鎖狀態(tài)表示并控制訪問,數(shù)字0表示沒有寫鎖被授權(quán)訪問。在讀鎖上分為悲觀鎖和樂觀鎖。鎖釋放以及其他相關(guān)方法需要使用郵編(stamps)變量作為參數(shù),如果他們和當前鎖狀態(tài)不符則失敗,這三種模式為:
      ? ? 寫入:方法writeLock可能為了獲取獨占訪問而阻塞當前線程,返回一個stamp變量,能夠在unlockWrite方法中使用從而釋放鎖。也提供了tryWriteLock。當鎖被寫模式所占有,沒有讀或者樂觀的讀操作能夠成功。
      ? ? 讀?。悍椒╮eadLock可能為了獲取非獨占訪問而阻塞當前線程,返回一個stamp變量,能夠在unlockRead方法中用于釋放鎖。也提供了tryReadLock。
      ? ? 樂觀讀?。悍椒╰ryOptimisticRead返回一個非0郵編變量,僅在當前鎖沒有以寫入模式被持有。如果在獲得stamp變量之后沒有被寫模式持有,方法validate將返回true。這種模式可以被看做一種弱版本的讀鎖,可以被一個寫入者在任何時間打斷。樂觀讀取模式僅用于短時間讀取操作時經(jīng)常能夠降低競爭和提高吞吐量。

FutureTaskhjaha

  • Callable和Runable接口對比

  • Furure接口

    • 可以得到別的線程任務(wù)方法的返回值
  • FutureTask類(實現(xiàn)Callble和Runable接口)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容