CountDownLatch

  • 时间:
  • 浏览:2
  • 来源:uu快3官网_uu快3登入

时间=11:05:01:952 -工作进程- thread=T-1 结束了获取资源

    public CountDownLatch(int count) {

一一俩个 CountDownLatch通过一一俩个 值为1的count被初始化,来作为一一俩个 开/关的门或门闩:所有调用了await()的进程前会在门前等待的图片 ,直到门被一一俩个 进程通过调用countDown()打开。

    public void await() throws InterruptedException {

        sync.releaseShared(1);

 - 而且head的waitStatus=0如此 修改head.waitStatus=PROPAGATE

                int c = getState();

countDown是将计数器减1,其本质是释放一次锁。

时间=11:05:01:952 准备等待的图片 工作进程执行

        }

            // Decrement count; signal when transition to zero

 - 唤醒head后的Node对应的进程。唤醒时重新执行setHeadAndPropagate。

而且node是队列中第一一俩个 等待的图片 进程,如此 尝试获取读锁,获取成功后更新队列的head,而且后一一俩个 节点也是等待的图片 读锁,如此 上端一一俩个 节点的进程进程。许多过程实现读锁共享。

                    }

                        continue;            // loop to recheck cases

            Node h = head;

                    int r = tryAcquireShared(arg);

            }

    public final boolean releaseShared(int arg) {

当第一一俩个 进程被唤醒完后 ,继续执行doAcquireSharedInterruptibly()土措施的for循环,在此循环中执行到setHeadAndPropagate土措施时,会将更新head,传播唤醒操作。

    }

一一俩个 被初始化为N的CountDownLatch可不时要被用来“在N个进程都完成了一种操作(而且许多操作而且被完成了N次)完后 创建一一俩个 进程”。

         * signal. But if it does not, status is set to PROPAGATE to

    }

CountDownLatch和ReentrantLock有许多类式的地方,而且类式偏离 内容而且在博客《ReentrantLock详解》中讨论过了,本文前会再次删改讨论。

                break;

时间=11:05:02:998 -工作进程- thread=T-0 资源释放完成

                }

            throw new InterruptedException();

                    continue;                // loop on failed CAS

                }

                        failed = false;

public static void main(String[] args) {

    CountDownLatch countDownLatch = new CountDownLatch(3);

    for (int i = 0; i < 3; i++) {

        String name = "T-"+i;

        Thread thread = new Thread(() -> {

         * unparkSuccessor, we need to know if CAS to reset status

private static void doTask(String name){

                final Node p = node.predecessor();

        return false;

        if (tryReleaseShared(arg)) {

创建一一俩个 SHARED类型的节点,加入到等待的图片 队列中。

            if (h != null && h != tail) {

        for (;;) {

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

        try {

时间=11:05:01:952 -工作进程- thread=T-0 结束了获取资源

                if (ws == Node.SIGNAL) {

CountDownlatch是一一俩个 多功能的同步工具,可不时要被用于各种目的。

此土措施将原困当前进程等待的图片 ,直到CountDownLatch通过countDown()土措施使计数器值为0

    }

                if (p == head) {

                if (shouldParkAfterFailedAcquire(p, node) &&

 - 循环进行以上一俩个 操作直到成功、而且head不曾变动过方才退出循环。

此土措施的主要作用是让获取可不能能 了锁的进程挂起,通过向等待的图片 队列中加上一一俩个 Node(此Node与当前进程相关联);接着判断是应该唤醒还是挂起。而且node是队列中第一一俩个 有效节点,如此 唤醒对应的进程;而且通过LockSupport挂起进程。具体逻辑如下:

计数器减1操作,当计数器减到0时,调用await的进程将被唤醒。

         * fails, if so rechecking.

                        return;

    }

            for (;;) {

判断算不算应该挂起当前节点对应的进程,而且应该挂起,则通过LockSupport挂起进程。

    }

            }

            doReleaseShared();

    private void doReleaseShared() {

                    if (r >= 0) {

CountDownLatch是基于AbstractQueuedSynchronizer(AQS)实现的,其通过state作为计数器。构造CountDownLatch时初始化一一俩个 state,完后 每调用countDown土措施一次,state减1;当state=0时,唤醒在await上被挂起的进程。

        boolean failed = true;

        }

        /*

         * while we are doing this. Also, unlike other uses of

            doAcquireSharedInterruptibly(arg);

释放锁,即将计数器-1;而且减-1后state=0,则表示删改的锁而且释放完了,当且仅当此时返回true。

    public final void acquireSharedInterruptibly(int arg)

        }

        protected boolean tryReleaseShared(int releases) {

                    return nextc == 0;

时间=11:05:01:952 -工作进程- thread=T-2 结束了获取资源

时间=11:05:01:994 -工作进程- thread=T-0 结束了使用资源,执行任务

时间=11:05:02:993 -工作进程- thread=T-2 资源释放完成

            throws InterruptedException {

        if (tryAcquireShared(arg) < 0)

而且state=0,即计数器的值为0,返回1,表示前会等待的图片 ;而且返回-1,可表示还时要等待的图片 。

            if (h == head)                   // loop if head changed

以下是输出结果,可不时要看多主进程等待的图片 的图片 一俩个工作进程执行完完后 才结束了执行。

        }

CountDownLatch是一一俩个 同步的辅助类,它前会可不能能 使一一俩个 进程等待的图片 许多进程完成人个的工作后再执行。

setHeadAndPropagate传播行为的逻辑如下:

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

    }

    private void doAcquireSharedInterruptibly(int arg)

         */

CountDownLatch是一一俩个 计数(构造函数中指定此数值)的锁,当通过countDown土措施将此计数值减为0前会唤醒完后 调用await的进程。一般用于当许多任务执行完后 ,在执行许多任务的场景中。

                else if (ws == 0 &&

当通过countDown操作将计数器的值改为0完后 ,通过doReleaseShared()土措施中unparkSuccessor(h)代码的唤醒等待的图片 队列中的一一俩个 等待的图片 进程。

 - 设置将此次唤醒Node的进程信息清空,而且设置为新的head,

                int nextc = c-1;

        if (Thread.interrupted())

            for (;;) {

                    throw new InterruptedException();

进程被唤醒完后 ,设置中断标志位。

                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))

 - 而且head的waitStatus=SIGNAL如此 修改head.waitStatus=0,而且唤醒head上端的一一俩个 等待的图片 被唤醒的进程。

                    parkAndCheckInterrupt())

                        p.next = null; // help GC

                if (c == 0)

        this.sync = new Sync(count);

                cancelAcquire(node);

        } finally {

        }

                int ws = h.waitStatus;

时间=11:05:01:997 -工作进程- thread=T-1 结束了使用资源,执行任务

         * in-progress acquires/releases.  This proceeds in the usual

            return true;

                    return false;

    }

                        setHeadAndPropagate(node, r);

        throws InterruptedException {

时间=11:05:02:998 -工作进程- thread=T-1 资源释放完成

时间=11:05:02:999 工作进程而且执行完

唤醒head后的一一俩个 处于挂起情况报告的进程。主要逻辑如下:

         * ensure that upon release, propagation continues.

         * way of trying to unparkSuccessor of head if it needs

CountDownLatch的计数器state可不能能 了被重置,而且时要一种能重置count的版本,可不时要考虑使用CyclicBarrier。

         * Additionally, we must loop in case a new node is added

            }

时间=11:05:01:991 -工作进程- thread=T-2 结束了使用资源,执行任务

        final Node node = addWaiter(Node.SHARED);

                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))

        protected int tryAcquireShared(int acquires) {

         * Ensure that a release propagates, even if there are other

                    unparkSuccessor(h);

        sync.acquireSharedInterruptibly(1);

CountDownLatch是通过一一俩个 计数器来实现的,计数器的初始值为等待的图片 进程数量。

            if (failed)

以下示例中,朋友 初始化CountDownLatch的信号量是3,如此 可不能能 了调用三次countDownLatch.countDown()时,完后 通过countDownLatch.await()的进程不可不能能 被唤醒。

接下来无限循环,尝试进行以下操作,直到获取到锁而且而且撤出 获取锁而被唤醒。

    public void countDown() {

                if (compareAndSetState(c, nextc))