日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

聊聊高并发(二十六)解析java.util.concurrent各个组件(八) 理解CountDownLatch闭锁

發布時間:2024/1/17 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 聊聊高并发(二十六)解析java.util.concurrent各个组件(八) 理解CountDownLatch闭锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CountDownLatch閉鎖也是基于AQS實現的一種同步器,它表示了“所有線程都等待,直到鎖打開才繼續執行”的含義。它和Semaphore的語意不同, Semaphore的獲取和釋放操作都會修改狀態,都可能讓自己或者其他線程立刻拿到鎖。而閉鎖的獲取操作只判斷狀態是否為0,不修改狀態本身,閉鎖的釋放操作會修改狀態,每次遞減1,直到狀態為0。

所以正常情況下,閉鎖的獲取操作只是等待,不會立刻讓自己獲得鎖,直到釋放操作把狀態變為0。

閉鎖可以用來實現很多場景,比如:

1. 某個服務依賴于其他服務的啟動才能啟動,就可以讓這個服務在其他服務狀態的閉鎖上等待

2. 某個游戲,必須等所有就緒者都到達才能開始游戲

3. 啟動一組相關的線程

4. 等待一組相關線程結束

?

來看看CountDownLatch的代碼。它也提供了一個內部類Sync來繼承AQS

1. CountDownLatch可以讓多個線程同時進入臨界區,所以也是共享模式的AQS

2. 獲取操作只是判斷狀態是否為0,即是否可以結束等待,進入臨界區

3. 釋放操作是對狀態遞減1,所以叫CountDown,類似報數的意思

?

?
  • private static final class Sync extends AbstractQueuedSynchronizer {

  • private static final long serialVersionUID = 4982264981922014374L;

  • ?
  • Sync(int count) {

  • setState(count);

  • }

  • ?
  • int getCount() {

  • return getState();

  • }

  • ?
  • protected int tryAcquireShared(int acquires) {

  • return (getState() == 0) ? 1 : -1;

  • }

  • ?
  • protected boolean tryReleaseShared(int releases) {

  • // Decrement count; signal when transition to zero

  • for (;;) {

  • int c = getState();

  • if (c == 0)

  • return false;

  • int nextc = c-1;

  • if (compareAndSetState(c, nextc))

  • return nextc == 0;

  • }

  • }

  • }

  • ?

    ?

    CountDownLatch維護了一個狀態表示Count的總數,釋放一次對這個總數減1直到為0,它的tryXXX方法傳遞的參數沒有實際意義,只是為了適應接口。

    如果獲取失敗,就進入AQS等待,直到等待結束后,以共享的方式在AQS隊列中釋放線程。

    CountDownLatch常用的方法就兩個: await()和countDown()

    ?

    ?
  • public CountDownLatch(int count) {

  • if (count < 0) throw new IllegalArgumentException("count < 0");

  • this.sync = new Sync(count);

  • }

  • ?
  • // 等待就相當于獲取操作

  • public void await() throws InterruptedException {

  • ??????? sync.acquireSharedInterruptibly(1);

  • ??? }

  • // 限時等待

  • public boolean await(long timeout, TimeUnit unit)

  • ??????? throws InterruptedException {

  • ??????? return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));

  • ??? }

  • ?
  • public void countDown() {

  • ??????? sync.releaseShared(1);

  • ??? }

  • ?

  • 設計1個測試用例來測試CountDownLatch閉鎖的功能

    ?

    1.? 創建1個二元閉鎖startLatch,只有1和0兩種狀態,也就是說只執行一次countDown()就可以打開閉鎖。這個startLatch用來阻塞線程,直到主線程說可以開始了

    2.? 創建1個狀態為n的endLatch,線程執行完就調用一次countDown,主線程在endLatch阻塞,直到n個線程都執行了countDown()報數,主線程才打印結束

    ?

    ?

    ?
  • package com.zc.lock;

  • ?
  • import java.util.concurrent.CountDownLatch;

  • ?
  • public class CountDownLatchUsecase {

  • private int nThreads;

  • ?
  • private CountDownLatch startLatch;

  • ?
  • private CountDownLatch endLatch;

  • ?
  • public CountDownLatchUsecase(int n){

  • this.nThreads = n;

  • startLatch = new CountDownLatch(1);

  • endLatch = new CountDownLatch(nThreads);

  • }

  • ?
  • public void race() throws InterruptedException{

  • System.out.println("Thread " + Thread.currentThread().getName() + " is waiting the resource");

  • startLatch.await();

  • System.out.println("Thread " + Thread.currentThread().getName() + " got the resource");

  • endLatch.countDown();

  • }

  • ?
  • public void start(){

  • startLatch.countDown();

  • }

  • ?
  • public void end() throws InterruptedException{

  • endLatch.await();

  • }

  • ?
  • public static void main(String[] args) throws Exception{

  • final CountDownLatchUsecase usecase = new CountDownLatchUsecase(10);

  • for(int i = 0; i < 10; i++){

  • Thread t = new Thread(new Runnable(){

  • ?
  • @Override

  • public void run() {

  • try {

  • usecase.race();

  • } catch (InterruptedException e) {

  • e.printStackTrace();

  • }

  • }

  • ?
  • }, String.valueOf(i));

  • t.start();

  • }

  • ?
  • Thread.sleep(3000);

  • ?
  • System.out.println("Now start!!!");

  • usecase.start();

  • usecase.end();

  • System.out.println("All Thread finished");

  • ?
  • }

  • }


  • 測試結果: 所有線程都等待,直到主線程說開始。所有線程都執行了countDown()之后,主線程才說結束

    ?

    ?

    ?
  • Thread 0 is waiting the resource

  • Thread 2 is waiting the resource

  • Thread 3 is waiting the resource

  • Thread 1 is waiting the resource

  • Thread 4 is waiting the resource

  • Thread 5 is waiting the resource

  • Thread 6 is waiting the resource

  • Thread 7 is waiting the resource

  • Thread 8 is waiting the resource

  • Thread 9 is waiting the resource

  • Now start!!!

  • Thread 0 got the resource

  • Thread 2 got the resource

  • Thread 3 got the resource

  • Thread 8 got the resource

  • Thread 7 got the resource

  • Thread 6 got the resource

  • Thread 5 got the resource

  • Thread 1 got the resource

  • Thread 4 got the resource

  • Thread 9 got the resource

  • All Thread finished

  • 總結

    以上是生活随笔為你收集整理的聊聊高并发(二十六)解析java.util.concurrent各个组件(八) 理解CountDownLatch闭锁的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。