併發編程(十):AQS之CyclicBarrier

一,底層AQS源碼分析:併發編程(四):AbstractQueuedSynchronizer源碼分析

二,CyclicBarrier介紹

    1,線程處理

        * CyclicBarrier 的字面意思就是循環屏障。在一組線程到達循環屏障時阻塞,直到最後一個線程到達屏障時,屏障纔會放開,讓所有線程執行。該類可以與 CountDownLatch 進行類比,功能基本一致。不同點在於 CyclicBarrier 的循環概念,CountDownLatch 爲一次性屏障,放開之後不會再對後續線程進行攔截,CyclicBarrier 一次放開之後會把屏障值設置爲初始狀態,循環進行屏障!

    2,類圖

        * 其實從類圖中不能看到任何有用信息,CyclicBarrier 內部通過 ReentrantLock Condition 進行控制,實現循環屏障

    3,常用API

// 初始化重入鎖進行線程加鎖處理
private final ReentrantLock lock = new ReentrantLock();
// 初始化Condition進行線程阻塞和線程喚醒處理
private final Condition trip = lock.newCondition();
// CyclicBarrier初始化許可量
private final int parties;
// 屏障放開前最後一個線程會執行的線程類(爲null不執行)
private final Runnable barrierCommand;
// 表示一個循環屏障週期
private Generation generation = new Generation();
// 初始化CyclicBarrier,並傳遞屏障值
public CyclicBarrier(int parties);
// 初始化CyclicBarrier,並傳遞屏障值和barrierAction
CyclicBarrier(int parties, Runnable barrierAction)

    4,功能DEMO

package com.gupao;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * @author pj_zhang
 * @create 2019-09-15 11:33
 */
public class CyclicBarrierTest {

    public static void main(String[] args) throws InterruptedException {
        // 初始化 CyclicBarrier,並傳遞count爲3
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        // 因爲初始屏障爲3,但線程數量定位6,所以對於 cyclicBarrier 來說,會有兩次阻塞和兩次釋放
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "正在執行");
                // 每一個線程內部等待
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "執行完畢; " + System.currentTimeMillis());
            }, "thread_" + i).start();
            Thread.sleep(1000);
        }
    }
}

三,源碼分析

    1,初始化

        * CyclicBarrier(int parties)

public CyclicBarrier(int parties) {
	// 直接通過方法重載調用
	this(parties, null);
}

        * CyclicBarrier(int parties, Runnable barrierAction)

public CyclicBarrier(int parties, Runnable barrierAction) {
	if (parties <= 0) throw new IllegalArgumentException();
	this.parties = parties;
	this.count = parties;
	// 初始化屏障前執行線程,沒有則爲空
	this.barrierCommand = barrierAction;
}

    2,循環屏障

        * await(..):無論是顯示等待還是不顯示等待,最終都是殊途同歸,調用同一個底層類

public int await() throws InterruptedException, BrokenBarrierException {
	try {
		return dowait(false, 0L);
	} catch (TimeoutException toe) {
		throw new Error(toe); // cannot happen
	}
}
public int await(long timeout, TimeUnit unit)
	throws InterruptedException,
		   BrokenBarrierException,
		   TimeoutException {
	return dowait(true, unit.toNanos(timeout));
}

        * dowait(boolean timed, long nanos)

private int dowait(boolean timed, long nanos)
	throws InterruptedException, BrokenBarrierException,
		   TimeoutException {
	// lock:重入鎖,已在常量定義
	// 定義語句:private final ReentrantLock lock = new ReentrantLock();
	final ReentrantLock lock = this.lock;
	lock.lock();
	try {
		// 賦值當前循環屏障標識
		// 可以通過 reset() 方法對標識進行重置
		final Generation g = generation;
		// 循環屏障中斷
		if (g.broken)
			throw new BrokenBarrierException();
		// 線程中斷處理,
		if (Thread.interrupted()) {
			// 中斷處理後打破屏障
			breakBarrier();
			throw new InterruptedException();
		}
		// 此處表示對循環屏障的屏障值遞減,當減爲0時屏障放開
		int index = --count;
		if (index == 0) {  // tripped
			boolean ranAction = false;
			try {
				// 減爲0,表示當前線程是屏障放開前最後一個線程
				// 由屏障放開前最後一個線程,執行初始化傳遞的屏障線程
				final Runnable command = barrierCommand;
				if (command != null)
					command.run();
				ranAction = true;
				// 構造新的循環屏障,
				nextGeneration();
				return 0;
			} finally {
				// 循環屏障釋放異常,則打破屏障
				if (!ranAction)
					breakBarrier();
			}
		}

		// 前一步沒有放開,說明屏障還需等待,線程阻塞
		for (;;) {
			try {
				// timed判斷是限時阻塞還是直接阻塞
				if (!timed)
					// trip:Condition,已在常亮定義
					// 定義語句:private final Condition trip = lock.newCondition();
					trip.await();
				else if (nanos > 0L)
					// 此處返回剩餘時間
					nanos = trip.awaitNanos(nanos);
			} catch (InterruptedException ie) {
				// 異常後打破屏障
				if (g == generation && ! g.broken) {
					breakBarrier();
					throw ie;
				} else {
					Thread.currentThread().interrupt();
				}
			}
			
			// 循環屏障中斷處理
			if (g.broken)
				throw new BrokenBarrierException();

			// 標識被重置,不做任何處理
			if (g != generation)
				return index;
				
			// 限時等待超時處理
			if (timed && nanos <= 0L) {
				breakBarrier();
				throw new TimeoutException();
			}
		}
	} finally {
		lock.unlock();
	}
}

        * breakBarrier():打破循環屏障

private void breakBarrier() {
	// 設置參數true
	generation.broken = true;
	// 重置屏障值爲初始值
	count = parties;
	// 通過Condition喚醒全部阻塞線程進行執行
	trip.signalAll();
}

        * nextGeneration():說明當前屏障已經阻塞完成,進行下一次循環阻塞

private void nextGeneration() {
	// 通過Condition喚醒全部阻塞線程
	trip.signalAll();
	// 重置屏障值爲初始值
	count = parties;
	// 構建一個新的Generation,進行下一次循環
	generation = new Generation();
}

    3,屏障重置

        * reset()

public void reset() {
	final ReentrantLock lock = this.lock;
	lock.lock();
	try {
		// 打破循環屏障,已經被屏障的線程全部喚醒執行
		breakBarrier();
		// 構建下一個循環屏障
		nextGeneration();
	} finally {
		lock.unlock();
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章