Java multi-thread synchronization tools of CyclicBarrier

A, CyclicBarrier use

CyclicBarrier literally be understood as a direct thread running barrier, which allows a set of threads of execution to be blocked when a common barrier point, until the last thread of execution to the specified location, you set up a thread of execution will trigger operation; at the same time compared with CyclicBarrier CountDownLatch, it can be reset; here we look CyclicBarrier by using a simple example;

Instantiate an object and pass CyclicBarrier internal thread you want to control;

    public static void main(String[] args) {

        CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
            public void run() {
                System.out.println("所有线程集合");
            }
        });
        for (int i = 0; i < 3; i++) {
            new CyclicBarrierThread(i + "", cb).start();
        }

    }

Counting threaded code, calls to even CyclicBarrier whenever count of the await () method

public class CyclicBarrierThread extends Thread{
    
    private CyclicBarrier barrier;
    
    private String name;
    
    private int count;
    
    public CyclicBarrierThread(String name,CyclicBarrier barrier) {
        this.name=name;
        this.barrier=barrier;
        this.count=0;
    }
    
    public void run() {
        try {
            for(int i=0;i<10;i++) {
                
                Thread.sleep(100);
                COUNT ++ ; 
                System.out.println (name + "number of threads ---" + Thread.currentThread () getName ( ) + " start counting:." + COUNT);
                 IF (COUNT% 2 == 0) { / / every even number of times counted during a set 
                    barrier.await (); 
                    System.out.println (name . + "number of threads ---" + Thread.currentThread () getName ( ) + " collection is completed, continue to count" ); 
                } 
            } 
            
        } the catch (Exception E) {
             // the TODO Auto-Generated Block the catch 
            e.printStackTrace (); 
        } 

    } 
}

View Code Output

2 --- Thread-2 thread start counting: 1 
0 Number thread --- Thread-0 starts counting: 1 
No. 1 thread --- Thread-1 start counting: 1 
No. 2 threads --- Thread-2 starts counting : 2 
No. 1 thread --- thread-1 starts counting: 2 
0 threads --- thread-0 starts counting: 2 
All set of threads 
2 threads --- the Thread- 2 collection is completed, continue to count 
No. 1 thread - -Thread- a collection is completed, continue to count 
0 threads --- the Thread- 0 collection is completed, continue to count 
No. 2 threads --- thread-2 start counting: 3 
No. 1 thread --- thread-1 start counting: 3 
0 No. thread --- thread-0 starts counting: 3 
No. 2 threads --- thread-2 start counting: 4 
No. 0 threads --- thread-0 starts counting: 4 
No. 1 thread --- thread-1 counted: 4 
All set of threads 
No. 1 thread --- Thread-  1 collection is completed, the count continues
No. 2 thread --- the Thread- 2 collection is completed, continue to count 
0 threads --- the Thread- 0 collection is completed, continue to count 
number of threads 0 --- Thread-0 starts counting: 5 
2 Number of threads --- Thread-2 counting: 5 
1 thread --- thread-1 counted: 5 
0 threads --- thread-0 starts counting: 6 
No. 1 thread --- thread-1 starts counting: 6 
2 threads --- the thread counting -2: 6 
All set of threads 
2 threads --- the Thread- 2 collection is completed, continue to count 
0 threads --- the Thread- 0 collection is completed, continue to count 
No. 1 thread --- the Thread- a collection is completed, continued count 
number of threads 0 --- thread-0 starts counting: 7 
No. 1 thread --- thread-1 counted: 7 
No. 2 threads --- thread-2 start counting: 7 
No. 1 thread --- thread-1 starts count: 8 
0 threads --- thread-0 starts counting: 8 
No. 2 threads --- Thread-2 start counting: 8 
All set of threads 
2 threads --- the Thread- 2 collection is completed, continue to count 
0 threads --- the Thread- 0 set complete, continue to count 
No. 1 thread --- the Thread- a collection is completed, continue to count 
number of threads 0 --- thread-0 starts counting: 9 
No. 1 thread starts counting --- thread-1: 9 
No. 2 threads --- thread-2 start counting: 9 
No. 1 thread --- thread-1 start counting: 10 
0 of the thread --- thread-0 starts counting: 10 
No. 2 threads --- thread-2 starts counting: 10 
All set of threads 
1 No. thread --- the Thread- . 1 collection is completed, continue to count 
No. 2 threads --- the Thread- 2 collection is completed, continue to count 
number of threads 0 --- thread-0 collection is completed, continue counting

You can see by the output, counting each thread count to use CyclicBarrier even times when the await () method, the thread will enter the state block waiting until the last thread reaches the barrier point, you define triggers a thread of execution, and the CyclicBarrier the await () method can be used repeatedly.

Two, CyclicBarrier source code analysis

Here we are on the inside of the CyclicBarrier source implementation of some analysis and summary

1, CyclicBarrier construction

First look at the constructor of CyclicBarrier

    public a CyclicBarrier ( int parties, the Runnable barrierAction) {
         IF (parties <= 0) the throw  new new an IllegalArgumentException ();
         // knockdown number of threads 
        the this .parties = parties;
         // for counting count values, each one thread to execution a barrier point, will be decremented. 1 
        the this .count = parties;
         // interceptor defined thread 
        the this .barrierCommand = barrierAction; 
    }

CyclicBarrier constructor was simply receiving a thread of execution you want to block and the number of threads defined.

2, await method

    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }

We look at specific implementation methods to achieve dowait

    Private  int dowait ( Boolean Timed, Long of nanos)
         throws InterruptedException, a BrokenBarrierException, 
               a TimeoutException { 
        // Get reentrant lock 
        Final of ReentrantLock = Lock the this .lock;
         // lock 
        Lock.lock ();
         the try {
             // a CyclicBarrier defined internally a class Generation 
            Final Generation G = Generation; 

            // Analyzing Generation of a broken state 
            IF (g.broken)
                 the throw  new new a BrokenBarrierException (); 

            // if the thread is interrupted
            IF (Thread.interrupted ()) {
                 // Generation is broken is set to true, count value is reset, and wake up all threads 
                breakBarrier ();
                 the throw  new new InterruptedException (); 
            } 

            // COUNT value minus a 
            int index = - COUNT ;
             IF (index == 0) {   // If conunt is 0, indicating the last thread to the Great barrier 
                Boolean ranAction = to false ;
                 the try {
                     final the Runnable Command = barrierCommand;
                     IF ! (Command = null  )
                        command.run (); // execute your incoming thread 
                    ranAction = to true ; 
                    NextGeneration (); // wake up all the blocked thread, at the same time to reset the count value and Generation 
                    return 0 ; 
                } a finally {
                     IF (! ranAction)
                         // intercepting the thread is not normally performed, wake up all the threads, while the count value is reset, the broken Generation set to true 
                        breakBarrier (); 
                } 
            } 

            // Loop an until TRIPPED, broken, interrupted, or Timed OUT 
            for (;;) {
                 the try{
                     // if timeout set obstruction
                    IF (! the Timed)
                         // release the current lock 
                        trip.await (); // false representation is not provided, has been blocking 
                    the else  IF (nanos> 0L ) 
                        nanos = trip.awaitNanos (nanos); // to true to set the blocking timeout 
                } the catch (InterruptedException IE) {
                     IF (G Generation == &&! g.broken) { 
                        breakBarrier (); 
                        the throw IE; 
                    } the else {
                         // We're about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        Thread.currentThread().interrupt();
                    }
                }

                if (g.broken)
                    throw new BrokenBarrierException();

                if (g != generation)
                    return index;

                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } The finally {
             // release lock 
            lock.unlock (); 
        } 
    }

Dowait implementation flow method is very clear, and the count value by the Condition interface ReentrantLock cooperate with each other, provides the following functions:

1, when the need to intercept the thread reaches the barrier point invoked await get ReentrantLock lock to ensure thread-safe;

2, check the count value is 0, it is determined whether the last thread to reach the barrier, and if so execution required to trigger a thread of execution, call the Condition of signalAll method wakes up all the blocked thread, and resets the count value and the Generation category, safeguard CyclicBarrier available repeated;

3, if not the last thread, then await the call Condition method according to the parameters passed to release the lock and enter the resource block waiting until they were awakened;

3, reset method

It can be used to reset the active state CyclicBarrier

    public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //generation.broken设置为true,唤醒所有线程,count值重置
            breakBarrier();   
            nextGeneration(); 
        } finally {
            lock.unlock();
        }
    }
    
    
    private void nextGeneration() {
        // signal completion of last generation
        trip.signalAll();
        // set up next generation
        count = parties;
        generation = new Generation();
    }


    private void breakBarrier() {
        generation.broken = true;
        count = parties;
        trip.signalAll();
    }

breakBarrier () and nextGeneration (), the main difference between these two methods is that the former will generation.broken set to true, it means that if you call the reset method active reset state CyclicBarrier class, class CyclicBarrier current thread synchronization is being used It will be woken up or throw an exception;

4、getNumberWaiting方法

    public int getNumberWaiting() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return parties - count;
        } finally {
            lock.unlock();
        }
    }

Obviously getNumberWaiting method to get the current number of threads have been running to shield the point of waiting and blocked;

Third, the summary

Through the above analysis we can see the realization of the principle CyclicBarrier still comparatively simple and clear, mainly based on the combination of the counter ReentrantLock to synchronize multiple threads of control. The above is achieved with the use of analysis of internal CyclicBarrier classes, which are subject to inadequate and not the right place also pointed out that hope and generosity.

 

Focus on micro-channel public number to see more technical articles.

 

Guess you like

Origin www.cnblogs.com/dafanjoy/p/11110575.html