CyclicBarrier 源码

package cn.cyc.n1;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

public class S1 {
	private static CyclicBarrier c=new CyclicBarrier(3);
	public static void main(String[] args) throws InterruptedException {
		Task task = new Task(c);
		Thread t1 = new Thread(task);
		Thread t2 = new Thread(task);
		t1.start();t2.start();
		LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
		c.reset();
		t1.join();t2.join();
		System.out.println("_______________");
		Thread t11 = new Thread(task);
		Thread t21 = new Thread(task);
		Thread t31= new Thread(task);
		t11.start();t21.start();t31.start();
	}
	
	 
}
class Task implements Runnable{
	private CyclicBarrier c;
	public Task(CyclicBarrier c){
		this.c=c;
	}
	
	public void run() {
		String e1=null;
		int a=-1;
		System.out.println(Thread.currentThread().getName()+" 启动");
		try {
			a=c.await();
		} catch (InterruptedException e) {
			e1="InterruptedException";
		} catch (BrokenBarrierException e) {
			e1="BrokenBarrierException";
		}
		if(e1!=null){System.out.println(Thread.currentThread().getName()+" 抛出异常,e="+e1);return;}
		System.out.println(Thread.currentThread().getName()+" *** 完毕 res="+a);
	}
	
}

输出:

Thread-0 启动
Thread-1 启动
Thread-1 抛出异常,e=BrokenBarrierException
Thread-0 抛出异常,e=BrokenBarrierException
_______________
Thread-2 启动
Thread-3 启动
Thread-4 启动
Thread-4 *** 完毕 res=0
Thread-3 *** 完毕 res=1
Thread-2 *** 完毕 res=2
 

前面2个线程启动后,获取独占锁,由于线程计数器==1,会进入aqs条件队列等待(释放独占锁,挂起)。调用reset更新珊兰,会获取独占锁,打破珊兰(设置generation的broken状态为true,复位线程计数器,唤醒aqs条件队列节点)更新珊兰释放独占锁。前面2个线程节点被添加到线程等待队列,获取独占锁运行完await,由于珊兰被打破抛出异常BrokenBarrierException。珊兰reset执行了更新珊兰的操作(唤醒aqs条件队列等待节点,复位计数器,更新generation)完成复位,后3个线程可以正常使用珊兰。

分析:

CyclicBarrier(int parties, Runnable barrierAction) 构造器,初始化珊兰打开需要的线程数量,需要的线程数量珊兰计数器,以及打开时,最后到达的一个线程执行的任务,为null时候不执行任务。

private final ReentrantLock lock = new ReentrantLock(); 独占锁
private final Condition trip = lock.newCondition(); 独占锁锁上的条件。


breakBarrier 打破珊兰:设置generation的状态 true,初始化需要的线程数量,唤醒条件队列里被挂起的节点。
nextGeneration 更新珊兰:唤醒所有在条件队列上挂起的节点,初始化珊兰计数器,更generation。

await 等待:获取独占锁 如果珊兰被打破,抛出异常;如果线程被中断,打破珊兰,抛出异常;对需要的线程计数器-1,如果为0 说明所有线程已经到达珊兰位置,珊兰打开,运行构造器传入的任务,如果成功执行,更新珊兰,返回0,如果失败,打破珊兰异常退出;自旋 【如果是定时等待,则调用aqs条件队列定时等待,否则调用aqs条件队列非定时等待,如果被中断抛出异常,如果此时generation没有被更新且珊兰未被打破,则打破珊兰抛出异常,否则线程中断;如果珊兰被打破,抛出异常;如果generation被更新,返回计数器值;如果定时且超时,打破珊兰,抛出超时异常。】最后 释放独占锁。所有等待的线程,会由于某个线程中断 超时 打破珊兰 所有线程到达而结束。

reset 重置珊兰:获取独占锁,打破珊兰(设置generation的broken状态为true,设置珊兰所需线程计数器为初始值,唤醒aqs条件队列等待的节点)。更新珊兰(唤醒aqs条件队列等待的节点,设置珊兰打开所需线程计数器为初始值,更新generation),释放独占锁。如果有线程等待珊兰,立即调用此操作会使得等待的线程抛出异常。

猜你喜欢

转载自blog.csdn.net/liangwenmail/article/details/81536459