JDK1.8并发之CountDownLatch

本文详细介绍了JDK1.8中的并发工具类CountDownLatch的工作原理和实现,包括其如何利用AQS(AbstractQueuedSynchronizer)进行线程同步,以及在状态变更、线程阻塞与唤醒过程中的核心方法如acquireSharedInterruptibly、tryAcquireShared、doAcquireSharedInterruptibly等的分析。此外,还提到了park和unpark方法在CountDownLatch中的应用。
摘要由CSDN通过智能技术生成

CountDownLatch

CountDownLatch 是java.util.concurrent包中的类,初始化时需要一个正整数参数作为初始 status 值,Thread#1 中每次调用它的countDown()方法都使得 status 减一,Thread#2 中调用它的await()方法会导致 Thread#2 阻塞直到 status 为0。

它可以用来设置一个任务阻塞直到其他 n 个相互独立的任务结束。

JDK1.8 源码注释中的一个例子如下:

class Driver { // ...
  void main() throws InterruptedException {
    CountDownLatch startSignal = new CountDownLatch(1);
    CountDownLatch doneSignal = new CountDownLatch(N);

    for (int i = 0; i < N; ++i) // create and start threads
      new Thread(new Worker(startSignal, doneSignal)).start();

    doSomethingElse();            // 开始前的准备工作
    startSignal.countDown();      // 使得所有的工作线程开始
    doSomethingElse();
    doneSignal.await();           // 等待所有工作线程结束
  }
}

class Worker implements Runnable {
  private final CountDownLatch startSignal;
  private final CountDownLatch doneSignal;
  Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
    this.startSignal = startSignal;
    this.doneSignal = doneSignal;
  }
  public void run() {
    try {
      startSignal.await(); // 等待开始信号
      doWork();
      doneSignal.countDown(); // 执行完任务后通知管理者
    } catch (InterruptedException ex) {} // return;
  }

  void doWork() { ... }
}

源码分析:

CountDownLatch 只有一个同步器字段,它是一个内部类的 final 实例,这个内部类是 java.util.concurrent.locks包中的 AbstractQueuedSynchronizer 的子类,重写了父类的 tryAcquireShared、tryReleaseShared 方法。它是一个共享式队列同步器。

AQS 要求子类重写的这两个方法,必须是非阻塞、线程安全的。

private final Sync sync; // CountDownLatch 构造时用正整数参数来初始化

private static final class Sync extends AbstractQueuedSynchronizer {
   
    private static final long serialVersionUID = 4982264981922014374L;
    Sync(int count) {
        setState(count);
    }

    int getCount() {
        return getState();
    }

    // 共享模式下,询问同步器当前 status 的值的状态,来表示现在是否能获得同步器
    protected int tryAcquireShared(int acquires) {
        return (getState() == 0) ? 1 : -1;
    }

    // 共享模式下,修改同步器的 status 值,来表示释放的动作
    protected boolean tryReleaseShared(int releases) {
        // 如果同步锁的 status 已经为 0,就返回 false。
        // 否则当前线程将 status减 1;
        // 操作成功时,如果减小后的新值为 0,返回 true,否则返回 false
        for (;;) {
            int c = getState();
            if (c == 0)
                return false;
            int nextc = c-1;
            
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值