1. 程式人生 >實用技巧 >其它 >C++中 NULL 和 nullptr 區別

C++中 NULL 和 nullptr 區別


所有的執行緒必須同時到達柵欄位置,才能繼續執行。柵欄用於等待其他執行緒。

CyclicBarrier可以使一定數量的執行緒反覆地在柵欄位置處彙集。當執行緒到達柵欄位置時將呼叫await方法,這個方法將阻塞直到所有執行緒都到達柵欄位置。如果所有執行緒都到達柵欄位置,那麼柵欄將開啟,此時所有的執行緒都將被釋放,而柵欄將被重置以便下次使用。

CyclicBarrier預設的構造方法是CyclicBarrier(int parties),其引數表示屏障攔截的執行緒數量,每個執行緒使用await()方法告訴CyclicBarrier我已經到達了屏障,然後當前執行緒被阻塞。

CyclicBarrier的另一個建構函式CyclicBarrier(int parties, Runnable barrierAction),用於執行緒到達屏障時,優先執行barrierAction,方便處理更復雜的業務場景。

以上內容參考:https://blog.csdn.net/qq_38293564/article/details/80558157

demo:

public class CycleBarrierTest {
    public static void main(String[] args) {
        CyclicBarrier cb = new CyclicBarrier(3);
        for (int i = 0; i < 3; i++) {
            System.out.println("建立工作執行緒" + i);
            Thread t = new Thread(new Worker(cb));
            t.start();
        }
    }

    static class Worker implements Runnable {
        private CyclicBarrier cb;
        public Worker(CyclicBarrier cb){
            this.cb = cb;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + "開始等待其他執行緒...");
                cb.await();
                System.out.println(Thread.currentThread().getName() + "執行完成...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

原始碼分析:

CyclicBarrier的await()方法

    /**
     * Main barrier code, covering the various policies.
     */
    private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 當前代
            final Generation g = generation;
            // 如果這個代損壞了,就丟擲異常
            if (g.broken)
                throw new BrokenBarrierException();
            // 如果執行緒中斷,則喚醒所有執行緒, 重置代和count
            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }

            int index = --count;

            // 當index ==0 的時候,則為最後一個執行緒呼叫該方法。
            if (index == 0) {  // tripped
                // 損壞狀態識別符號
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    // 執行建構函式為CyclicBarrier(int parties, Runnable barrierAction)的barrierAction的run方法
                    if (command != null)
                        command.run();
                    ranAction = true;
                    // 喚醒所有執行緒, 重置代和count
                    nextGeneration();
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }

            // loop until tripped, broken, interrupted, or timed out
            for (;;) {
                try {
                    // 如果沒有時間限制,就等待,直到被喚醒
                    if (!timed)
                        trip.await();
                    else if (nanos > 0L)
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    if (g == generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } 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;
                // 如果有時間限制且小於0,則喚醒所有執行緒, 重置代和count並丟擲異常
                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
            lock.unlock();
        }
    }

在CyclicBarrier中,同一批執行緒屬於同一代。當有parties個執行緒到達barrier之後,generation就會被更新換代。其中broken標識該當前CyclicBarrier是否已經處於中斷狀態。

CountDownLatch一般用於某個執行緒A等待若干其他執行緒完成後,它才執行; 而CyclicBarrier一般用於一組執行緒互相等待至某個狀態,然後一組執行緒再同時執行。

CountDownLatch強調一個執行緒等多個執行緒完成某件事情;CyclicBarrier是多個執行緒互等,等大家完成,再攜手共進。