1. 程式人生 > >Java併發程式設計實戰:閉鎖CountDownLatch,柵欄CyclicBarrier與訊號量Semaphore

Java併發程式設計實戰:閉鎖CountDownLatch,柵欄CyclicBarrier與訊號量Semaphore

整體上對三個概念進行一個說明:

CountDownLatch和CyclicBarrier都能夠實現執行緒之間的等待,只不過它們側重點不同:

  • CountDownLatch是閉鎖,相當於一扇門:在閉鎖達到結束狀態之前,這扇門一直是關閉的,並且沒有任何執行緒能夠通過,當到達結束狀態時,這扇門會開啟,允許所有執行緒通過。當閉鎖到達結束狀態之後,將不會再改變狀態,將永遠保持開啟狀態。
  • 柵欄能夠阻塞一組執行緒,直到某個事件發生。當執行緒到達柵欄位置將呼叫await()方法,這個方法將阻塞直到所有執行緒都到達柵欄位置。如果所有執行緒都到達柵欄位置,那麼柵欄將開啟,所有執行緒都被釋放,而柵欄將被重置以便下次使用。
  • 閉鎖與柵欄的關鍵區別在於,所有執行緒必須同時到達柵欄位置,才能繼續執行。閉鎖用於等待時間,而柵欄用於等待其他執行緒。閉鎖是一次性物件,一旦進入終止狀態,就不能被重置。

計數訊號量(Counting Semaphore)用來控制同時訪問某個特定資源的運算元量,或者同時執行某個指定操作的數量。Semaphore還可以用來實現某種資源池或對容器施加邊界。Semaphore管理一組虛擬的許可(permit)

具體可以參見一篇博文:Java併發程式設計:CountDownLatch、CyclicBarrier和Semaphore

其中有處關於Semaphore的release()的解釋感覺講解的不太準確,參考官方api進行一個更正:

/**
    * Releases a permit, returning it to the semaphore.
    *
    * <p>Releases a permit, increasing the number of available permits by
    * one.  If any threads are trying to acquire a permit, then one is
    * selected and given the permit that was just released.  That thread
    * is (re)enabled for thread scheduling purposes.
    *
    * <p>There is no requirement that a thread that releases a permit must
    * have acquired that permit by calling
    * Correct usage of a semaphore is established by programming convention
    * in the application.
    */
   public void release() {
       sync.releaseShared(1);
   }

一個執行緒呼叫release()方法前不是必須得呼叫過acquire()方法,但是最後一句提到:semaphore正確的用法應該由應用程式去建立
可以將acquire()視為是消費一個許可,而release()操作是建立一個許可,Semaphore並不受限於它在建立時的初始許可數量
Semaphore其實和鎖有點類似,它一般用於控制對某組資源的訪問許可權