1. 程式人生 > >【Java】J.U.C併發包

【Java】J.U.C併發包

簡介

Java併發包(java.util.concurrent)中提供了很多併發工具,這其中,很多我們耳熟能詳的併發工具,譬如ReentrantLock、Semaphore,CountDownLatch,CyclicBarrier,它們的實現都用到了一個共同的基類 - AbstractQueuedSynchronizer,簡稱AQS。AQS提供了一種原子式管理同步狀態、阻塞和喚醒執行緒功能以及佇列模型的簡單框架。是一個用來構建鎖和同步器的框架,使用AQS能簡單且高效地構造出應用廣泛的大量的同步器,比如我們提到的ReentrantLock,Semaphore,其他的諸如ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基於AQS的。

設計思想

同步器背後的基本思想非常簡單,可以參考AQS作者 Doug Lea 的論文:The java.util.concurrent Synchronizer Framework。同步器一般包含兩種方法,一種是acquire,另一種是release。

  • acquire操作阻塞呼叫的執行緒,直到同步狀態允許其繼續執行。
  • release操作則是改變同步狀態,使得一或多個被acquire阻塞的執行緒繼續執行。

其中acquire操作虛擬碼如下:

while (synchronization state does not allow acquire) {
    enqueue current thread if
not already queued; possibly block current thread; } dequeue current thread if it was queued;

release操作虛擬碼如下:

update synchronization state;
if (state may permit a blocked thread to acquire)
    unblock one or more queued threads;

為了實現上述操作,需要下面三個基本元件的相互協作:

  • 同步狀態的原子性管理;
  • 執行緒的阻塞與解除阻塞;
  • 佇列的管理;

AQS框架藉助於兩個類:Unsafe(提供CAS操作) 和 LockSupport(提供park/unpark操作)。

1. 同步狀態的原子性管理

AQS類使用單個int(32位)來儲存同步狀態,並暴露出getStatesetState以及compareAndSet操作來讀取和更新這個狀態。該整數可以表現任何狀態。比如, Semaphore 用它來表現剩餘的許可數,ReentrantLock 用它來表現擁有它的執行緒已經請求了多少次鎖;FutureTask 用它來表現任務的狀態(尚未開始、執行、完成和取消)。

如JDK的文件中所說,使用AQS來實現一個同步器需要覆蓋實現如下幾個方法,並且使用getStatesetStatecompareAndSetState這幾個方法來設定或者獲取狀態。

  • boolean tryAcquire(int arg)

  • boolean tryRelease(int arg)

  • int tryAcquireShared(int arg)

  • boolean tryReleaseShared(int arg)

  • boolean isHeldExclusively()

以上方法不需要全部實現,根據獲取的鎖的種類可以選擇實現不同的方法,支援獨佔(排他)獲取鎖的同步器應該實現tryAcquiretryReleaseisHeldExclusively而支援共享獲取的同步器應該實現tryAcquireSharedtryReleaseSharedisHeldExclusively。下面以 CountDownLatch 舉例說明基於AQS實現同步器, CountDownLatch 用同步狀態持有當前計數,countDown方法呼叫 release從而導致計數器遞減;當計數器為0時,解除所有執行緒的等待;await呼叫acquire,如果計數器為0,acquire 會立即返回,否則阻塞。

參考資料

相關推薦

JavaJ.U.C發包

簡介 Java併發包(java.util.concurrent)中提供了很多併發工具,這其中,很多我們耳熟能詳的併發工具,譬如ReentrantLock、Semaphore,CountDownLatch,CyclicBarrier,它們的實現都用到了一個共同的

JavaJ.U.C併發包 - AQS機制

簡介 Java併發包(java.util.concurrent)中提供了很多併發工具,這其中,很多我們耳熟能詳的併發工具,譬如ReentrantLock、Semaphore,CountDownLatch,CyclicBarrier,它們的實現都用到了一個共同的基類 - Abstrac

J.U.C發包(1)

J.U.C併發包(1) AbstractQueuedSynchronizer AbstractQueuedSynchronizer是JUC併發包中鎖的底層支援,AbstractQueuedSynchronizer是抽象同步佇列,簡稱AQS,是實現同步器的基礎元件,併發包中鎖的實現底層就是使用AQS實現,

Java並發編程實戰—–“J.U.C”:ReentrantLock之二lock方法分析

b2c check 條件 維護 box 抽象 post eight 若是 前一篇博客簡介了ReentrantLock的定義和與synchronized的差別,以下尾隨LZ的筆記來扒扒ReentrantLock的lock方法。我們知道ReentrantLock有公平鎖、非

死磕Java並發—–J.U.C之AQS(一篇就夠了)

ini tle 循環 針對 可能 width als 如果 boolean [隱藏目錄]1 獨占式1.1 獨占式同步狀態獲取1.2 獨占式獲取響應中斷1.3 獨占式超時獲取1.4 獨占式同步狀態釋放2 共享式2.1 共享式

死磕Java併發-----J.U.C之AQS:阻塞和喚醒執行緒

此篇部落格所有原始碼均來自JDK 1.8 線上程獲取同步狀態時如果獲取失敗,則加入CLH同步佇列,通過通過自旋的方式不斷獲取同步狀態,但是在自旋的過程中則需要判斷當前執行緒是否需要阻塞,其主要方法在acquireQueued(): if (sho

死磕Java併發-----J.U.C之阻塞佇列:ArrayBlockingQueue

ArrayBlockingQueue,一個由陣列實現的有界阻塞佇列。該佇列採用FIFO的原則對元素進行排序新增的。 ArrayBlockingQueue為有界且固定,其大小在構造時由建構函式來決定,確認之後就不能再改變了。ArrayBlockingQueu

死磕Java併發—– J.U.C之併發工具類:Semaphore

此篇部落格所有原始碼均來自JDK 1.8訊號量Semaphore是一個控制訪問多個共享資源的計數

死磕Java併發—– J.U.C之AQS:同步狀態的獲取與釋放

此篇部落格所有原始碼均來自JDK 1.8在前面提到過,AQS是構建Java同步元件的基礎,我們期

死磕Java併發-----J.U.C之併發工具類:Exchanger

此篇部落格所有原始碼均來自JDK 1.8 前面三篇部落格分別介紹了CyclicBarrier、CountDownLatch、Semaphore,現在介紹併發工具類中的最後一個Exchange。Exchange是最簡單的也是最複雜的,簡單在於API非常簡

死磕Java併發-----J.U.C之Condition

此篇部落格所有原始碼均來自JDK 1.8 在沒有Lock之前,我們使用synchronized來控制同步,配合Object的wait()、notify()系列方法可以實現等待/通知模式。在Java SE5後,Java提供了Lock介面,相對於Synch

死磕Java併發-----J.U.C之重入鎖:ReentrantLock

此篇部落格所有原始碼均來自JDK 1.8 ReentrantLock,可重入鎖,是一種遞迴無阻塞的同步機制。它可以等同於synchronized的使用,但是ReentrantLock提供了比synchronized更強大、靈活的鎖機制,可以減少死鎖發生

死磕Java併發-----J.U.C之阻塞佇列:DelayQueue

DelayQueue是一個支援延時獲取元素的無界阻塞佇列。裡面的元素全部都是“可延期”的元素,列頭的元素是最先“到期”的元素,如果佇列裡面沒有元素到期,是不能從列頭獲取元素的,哪怕有元素也不行。也就是說只有在延遲期到時才能夠從佇列中取元素。 DelayQu

死磕Java併發-----J.U.C之併發工具類:CyclicBarrier

此篇部落格所有原始碼均來自JDK 1.8 CyclicBarrier,一個同步輔助類,在API中是這麼介紹的: 它允許一組執行緒互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的執行緒的程式中,這些執

死磕Java併發—–J.U.C之AQS(一篇就夠了)

作者:大明哥  原文地址:http://cmsblogs.com 越是核心的東西越是要反覆看,本文篇幅較長,希望各位細細品讀,來回多讀幾遍理解下。 AQS簡介 java的內建鎖一直都是備受爭議的,在JDK 1.6之前,synchronized這個重量級鎖其效能一直都

死磕Java併發-----J.U.C之AQS:AQS簡介

Java的內建鎖一直都是備受爭議的,在JDK 1.6之前,synchronized這個重量級鎖其效能一直都是較為低下,雖然在1.6後,進行大量的鎖優化策略(【死磕Java併發】—–深入分析synchronized的實現原理),但是與Lock相比synchroni

死磕Java併發-----J.U.C之AQS:CLH同步佇列

此篇部落格所有原始碼均來自JDK 1.8 CLH同步佇列是一個FIFO雙向佇列,AQS依賴它來完成同步狀態的管理,當前執行緒如果獲取同步狀態失敗時,AQS則會將當前執行緒已經等待狀態等資訊構造成一個節點(Node)並將其加入到CLH同步佇列,同時會

漫畫JAVA併發程式設計 J.U.C Lock包之ReentrantLock互斥鎖

在如何解決原子性問題的最後,我們賣了個關子,互斥鎖不僅僅只有synchronized關鍵字,還可以用什麼來實現呢? J.U.C包中還提供了一個叫做Locks的包,我好歹英語過了四級,聽名字我就能馬上大聲的說:Locks包必然也可以用作互斥! # ReentrantLock 我們可以通過從具體到抽象的方法來揭開

Java移動JDK路徑後,修改環境變量不生效 Error: could not open `C:Program FilesJavajre1.8.0_131libamd64jvm.cfg'

技術 alt OS log 修改環境變量 post home http hid 場景: JDK原先裝在C盤的,現在移動到了D盤,並在環境變量修改了%JAVA_HOME%的新路徑,但是CMD中輸入java後依然報錯。 Error: could not open `C:\Pro

高並發第八彈:J.U.C起航(java.util.concurrent)

思想 依賴 分享圖片 變量 ... 查找 沖突 dex http java.util.concurrent是JDK自帶的一個並發的包主要分為以下5部分: 並發工具類(tools) 顯示鎖(locks) 原子變量類(aotmic) 並發集合(collections) Exe