Java Concurrent Programming JUC: CyclicBarrier thread synchronization

Keywords: Java Back-end Concurrent Programming JUC

java.util.concurrent.CyclicBarrier provides a synchronization mechanism for multiple threads to wait for each other. It can be understood as an obstacle. All threads that reach the obstacle first will be in a waiting state. All threads can continue to execute until all threads reach the obstacle.

For example, the synchronization mode of CyclicBarrier is a bit like that when friends make an appointment to travel, they gather at the entrance of the scenic spot. The entrance of the scenic spot is a Barrier barrier, waiting for everyone to arrive before they enter the scenic spot together. After entering the scenic spot, we went to climb the mountain. Some people climbed fast and others climbed slowly. We made an appointment to gather at the top of the mountain, so the top of the mountain was another Barrier obstacle. We didn't go down the mountain until we all reached the top of the mountain.

The following is a diagram to illustrate this problem.

Each thread "waits for each other" at the CyclicBarrier barrier by calling await(). Once all threads reach the CyclicBarrier (all call the CyclicBarrier method), all threads will wake up again and continue to execute.

1. Create a CyclicBarrier barrier

When creating a CyclicBarrier, you need to specify how many threads need to be controlled for synchronization. For example, the following CyclicBarrier is set to control the synchronization of two threads.

CyclicBarrier barrier = new CyclicBarrier(2);

2. Wait at the CyclicBarrier obstacle

Call the await() method of CyclicBarrier to enter the wait state, which is usually called after the thread completes its stage task.

barrier.await();

CyclicBarrier also provides another method to specify the waiting timeout time. When the waiting time is greater than the timeout time, even if other threads do not call the await method, the thread will automatically wake up and continue to execute. (my friends have made an appointment to travel. I'll go first if you don't come after waiting for 10 minutes).

barrier.await(10, TimeUnit.SECONDS);

The waiting threads waits at theCyclicBarrieruntil either:

The condition that the thread waiting at the CyclicBarrier is released to continue execution (any of the following conditions can be met)

  • The last arriving thread calls the await() method
  • The thread was interrupted by another thread (another thread called its interrupt() method).
  • Another waiting thread was interrupted
  • Another waiting thread timed out while waiting at the CyclicBarrier.
  • An external thread called CyclicBarrier.reset() to remove the barrier.

3. CyclicBarrier Action

CyclicBarrier Action is not easy to understand. It can be understood as the behavior of the barrier itself. The Action action is a thread. After all threads reach the obstacle, the thread will be executed.

Runnable      barrierAction =   Create thread;
CyclicBarrier barrier  = new CyclicBarrier(2, barrierAction);

If this code still fails to understand the role of CyclicBarrier Action, see the following example.

4. CyclicBarrier example

The following code demonstrates how to use CyclicBarrier for thread synchronization:

Runnable barrier1Action = new Runnable() {
    public void run() {
        System.out.println("Obstacle 1 collection succeeded, and everyone arrived at the gate of the scenic spot ");
    }
};
Runnable barrier2Action = new Runnable() {
    public void run() {
        System.out.println("Obstacle 2 assembly succeeded and everyone reached the top of the mountain");
    }
};

//Barrier 1 entrance to scenic spot
CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);
//Obstacle 2 peak
CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);

//Tourism plan, stage goal 1: gather at the entrance of scenic spots
CyclicBarrierRunnable barrierRunnable1 =
        new CyclicBarrierRunnable(barrier1, barrier2);
//Tourism plan, stage goal 2: climb the mountain to the top of the mountain
CyclicBarrierRunnable barrierRunnable2 =
        new CyclicBarrierRunnable(barrier1, barrier2);

new Thread(barrierRunnable1).start();  //Visitor A, Thread-0
new Thread(barrierRunnable2).start();  //Visitor B, Thread-1

The following is a thread class CyclicBarrierRunnable. Starting one represents a visitor

public class CyclicBarrierRunnable implements Runnable{

    CyclicBarrier barrier1 = null;  //Obstacle 1
    CyclicBarrier barrier2 = null;  //Obstacle 2

    public CyclicBarrierRunnable( CyclicBarrier barrier1,CyclicBarrier barrier2) {
        this.barrier1 = barrier1;
        this.barrier2 = barrier2;
    }

    public void run() {
        try {
            Thread.sleep(1000);  //Here write the process code for going to the scenic spot
            System.out.println(Thread.currentThread().getName() +
                                " Arrive at the entrance of the scenic spot");
            this.barrier1.await();

            Thread.sleep(1000);  //Here write the process code of mountain climbing
            System.out.println(Thread.currentThread().getName() +
                                " Climb to the top of the mountain");
            this.barrier2.await();

            System.out.println(Thread.currentThread().getName() +
                                " Good play. Go down the mountain and go home!");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

The following output is the execution print result of the above code. If you execute the above code several times, you will find that the arrival order of Thread-0 and Thread-1 at obstacle 1 and obstacle 2 is uncertain, but it always arrives first and then continues to execute.

Thread-0 Arrive at the entrance of the scenic spot
Thread-1 Arrive at the entrance of the scenic spot
 Obstacle 1 collection succeeded, and everyone arrived at the gate of the scenic spot
Thread-1 Climb to the top of the mountain
Thread-0 Climb to the top of the mountain
 Obstacle 2 assembly succeeded and everyone reached the top of the mountain
Thread-0  Good play. Go down the mountain and go home!
Thread-1  Good play. Go down the mountain and go home!

Author: zimug
Link: https://juejin.cn/post/6945960442934067214

Posted by farkewie on Wed, 27 Oct 2021 08:52:27 -0700