In-depth understanding of CyclicBarrie

In-depth understanding of CyclicBarrier

Other knowledge points


In-depth understanding of Java multi-threading basics In-depth understanding of aqs
ReentrantLock usage In
-depth understanding of semaphore Semaphore
In-depth understanding of the three major features
of concurrency In-depth understanding of concurrent programming In-depth understanding of CAS
In-depth understanding of CountDownLatch
Java thread pool

Detailed usage of CyclicBarrier

Detailed usage of CyclicBarrier

Principle of Cyclic Barrier

Example debug to walk through the process

The player t1 t2 thread and the referee main thread are ready for the game.


    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {


       CyclicBarrier cyclicBarrier = new CyclicBarrier(3);


        new Thread(() -> {
            try {
                Thread.sleep(10_000);
                System.out.println("t1 在准备 ");
                cyclicBarrier.await();   // 等另外一个一个线程准备好 然后开始做事情
                System.out.println("t1 准备好了  ");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }

        },"t1").start();

        new Thread(() -> {
            try {
                Thread.sleep(5_000);
                System.out.println("t2 在准备  ");
                cyclicBarrier.await(); // 等另外一个一个线程准备好 然后开始做事情
                System.out.println("t2 准备好了  ");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        },"t2"  ).start();

        System.out.println(" 裁判 在准备 ");
        cyclicBarrier.await();
        System.out.println(" 裁判 准备好了 ");


        while (true){
            if (cyclicBarrier.getNumberWaiting()==0){
                System.out.println(" 时间到: 开始比赛");
                return;
            }
        }


    }
复制代码

operation result

insert image description here

debug runs the main thread first

insert image description here
no waiting time
insert image description here

specific methodprivate int dowait(boolean timed, long nanos)

You can see that ReentrantLockthe lock , and the count is reduced by one

insert image description here

Block the main thread

Here trip is a conditional queue

private final Condition trip = lock.newCondition();
insert image description here

You can see that a conditional node node is created here

insert image description here

addConditionWaiter method
insert image description here
then LockSupport.park(this); blocks the current thread

You can see that the main thread is already waiting, now let’s go to the t1 thread

insert image description here

Continue to follow the above counting down logic, at this time the count is still not equal to 0

insert image description here

Still will take the wait conditional queue method

insert image description here

Create a new thread node condition node, and enqueue

insert image description here
then continue to park
insert image description here

Next t2 thread await

insert image description here
It will be found that the t2 thread count is 0 at this time, and the nextGeneration(); method is executedinsert image description here

The current t2 thread executes the signalAll method to notify all?

count = parties; reset the counter
insert image description here

Enter the method, get the head node,

insert image description here
Execute the doSignalAll(first) method
to get the head node and set the next pointer to null
insert image description here
transferForSignal method

It is found that the state of the conditional node is set to 0 first, and then a new Node node is createdNode p = enq(node);

insert image description here
New node node

这段代码很熟悉,是aqs里构建同步队列以及入队的方法,可以明白t2线程将条件队列里所有的节点转为同步队列

Node p = enq(node);

t2 最后执行unlock

insert image description here

释放锁
insert image description here
这里是也是aqs里的释放锁 逻辑,同时将获取锁的线程置为null

insert image description here
唤醒其他线程

insert image description here

将 Node 节点状态置为 0

insert image description here

唤醒main线程

insert image description here

此时main线程被t2唤醒

insert image description here

同理main线程这里也执行置为当前线程锁的线程未null

insert image description here
然后unLock

insert image description here
继续唤醒其他线层 这里是t1

insert image description here
这里还是这个方法,和上面逻辑一样 也是aqs里的

insert image description here

可以看到t1被唤醒,此时三个线程都被是唤醒状态

insert image description here

此时将main线程执行到这里

insert image description here
将t1执行到这里

insert image description here

将t2执行到这里

insert image description here

最后
CyclicBarrier 构造,count是计数器, parties 是备份的计数器,barrierCommand 是传进来的任务
insert image description here

在 await 方法里 dowait 时候可以看到 计数器是 0 了 可以执行这个方法,可以用来做执行结束通知

insert image description here

最后看重置方法

insert image description here

重置,以及通知
insert image description here

最后

实现原理

CyclicBarrier是通过ReentrantLock的"独占锁"和Conditon来实现一组线程的阻塞 唤醒的,而CountDownLatch则是通过AQS的“共享锁”实现

CyclicBarrier执行流程

大概范围的一个执行流程,没有那么细。

  • 1 await() 先进行计数逻辑,然后将线程node节点放入条件队列
  • 2 最后一个await() 计数为 0 时,该线程将条件队列转换为同步队列,然后唤醒下一个同步队列节点,也就是去唤醒下一个线程
  • 3 其他线程被唤醒继续唤醒下一个线程,这里的流程和之前aqs流程是一样的,都是aqs里的逻辑。

都是在lock加锁和解锁里进行操作的

CyclicBarrier与CountDownLatch的区别

  • 1 The counter of CountDownLatch can only be used once, while the counter of CyclicBarrier can be reset using the reset() method. So CyclicBarrier can handle more complex business scenarios, such as if a calculation error occurs, you can reset the counter and let the threads execute it again
  • 2 CyclicBarrier also provides getNumberWaiting (you can get the number of threads blocked by CyclicBarrier), isBroken (used to know whether the blocked thread is interrupted) and other methods.
  • 3 CountDownLatch will block the main thread, and CyclicBarrier will not block the main thread, but only block the sub-threads.
  • 4 Both CountDownLatch and CyclicBarrier can realize the waiting between threads, but they have different emphases. CountDownLatch is generally used for one or more threads, waiting for other threads to complete the task before executing. CyclicBarrier is generally used for a group of threads to wait for each other to a certain state, and then this group of threads executes at the same time.
  • 5 CyclicBarrier can also provide a barrierAction to combine multi-thread calculation results.
  • 6 CyclicBarrier uses ReentrantLock's "exclusive lock" and Conditon to realize the blocking wakeup of a group of threads, while CountDownLatch is implemented through AQS' "shared lock"

CountDownLatch

In-depth understanding of CountDownLatch

Guess you like

Origin juejin.im/post/7231804086382084151