CyclicBarrier

1、CyclicBarrier:回环栅栏,可以让一组线程等待到某个状态,然后在全部通过并执行,可以复用。

	//parties 定义线程达到该值才可以放行
   public CyclicBarrier(int parties) {
        this(parties, null);
    }
	public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        //值
        this.parties = parties;
        this.count = parties;
        //到达定义的parties值,执行的任务。
        this.barrierCommand = barrierAction;
    }

2、底层使用的ReentrantLock 和Condition (条件等待队列)实现的。

代码

public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor =
                new ThreadPoolExecutor(10, 20, 10, TimeUnit.SECONDS, new ArrayBlockingQueue(10));
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        ReentrantLock reentrantLock = new ReentrantLock();

        for (int i = 0; i < 5; i++) {
            reentrantLock.lock();

            try {
                threadPoolExecutor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "线程等待");
                    try {
                    	/*
                    	* 获取锁->释放锁->进入条件等待队列、阻塞线程->(被singalAll线程唤醒,会把条件等待队列转为同步等待队列)获取锁(执行定义的任务)->释放锁(执行完任务释放锁)
                    	*/
                        cyclicBarrier.await();
                        /**
                         * 线程数够3个时开始执行
                         */
                        System.out.println("线程数达到3执行!");
                    } catch (InterruptedException|BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                });
            } finally {
			//唤醒的是同步等待队列的节点     
           reentrantLock.unlock();
            }
        }
    }

源码解析
await()源码(CyclicBarrier类的源码)


// cyclicBarrier.await();

 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();
            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }
			//计数器减一
            int index = --count;
            //如果count为0
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    /*
                    * 如果command 不为null 就执行传入的任务
                    */
                    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)
                    	/**
                    	*让该线程等待(Condition trip = lock.newCondition();)使用的是Condition
                    	* 调用AQS中的阻塞,入队
                    	* 直到被唤醒
                    	**/ 
                        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;
                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
        	//最终会调用release()方法
            lock.unlock();
        }
    }

/*
* 唤醒其他阻塞线程
*/
private void nextGeneration() {
        /*
        *	signal completion of last generation 上一代信号完成
        *	源码在下面AQS源码中
		*/ 
        trip.signalAll();
        // set up next generation
        count = parties;
        generation = new Generation();
 }

入队条件等待队列源码(AQS源码)

//  trip.await();
public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            //入队(入队逻辑)
            Node node = addConditionWaiter();
            /**
			* 释放锁的逻辑    fullyRelease();
			**/
            int savedState = fullyRelease(node);
            int interruptMode = 0;
            /*
            * 判断node是不是在同步等待队列中
            * 返回false当前场景,非得话为true 
            */
            while (!isOnSyncQueue(node)) {
            	//阻塞当前线程
                LockSupport.park(this);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
           	//同步等待队列出队
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }
        
//入队,条件队列,是一个单向链表
 private Node addConditionWaiter() {
            Node t = lastWaiter;
            // If lastWaiter is cancelled, clean out.
            if (t != null && t.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            //存放到链表中
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            //t==null是链表为null(代表刚创建的队列),头设置为当前值
            if (t == null)
                firstWaiter = node;
            else
            	//设置上一个节点的下一个节点
                t.nextWaiter = node;
            //尾设置为当前值    
            lastWaiter = node;
            return node;
        }
/*
*释放锁的逻辑
*/
 final int fullyRelease(Node node) {
        boolean failed = true;
        try {
        	/*
			* 获取锁的状态,由于前已经加锁,所以savedState 为1,
			* (独占锁)加锁把state由0改为1
			* 解锁把state由1改为0
			*/
            int savedState = getState();
            /*
			* 释放锁
			*/
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }
  /*
  * 释放锁
  * unparkSuccessor(h);
  * arg = 1
  */
  public final boolean release(int arg) {
  		/*
  		* 调用ReentrantLock 类中的tryRelease(arg) 解锁放法。
  		* 返回true释放锁成功
  		*/
        if (tryRelease(arg)) {
            Node h = head;
            /*
            * 这个快只有在同步队列不为null才会执行
            * 在当前例子中在,第三个线程解锁时执行该代码
            * CyclicBarrier源码的dowait()方法中最后的finally代码块lock.unlock();
			*/
            if (h != null && h.waitStatus != 0)
                //如果存在后继节点,唤醒后继节点
                unparkSuccessor(h);
            //释放锁成功    
            return true;
        }
        return false;
    }
/*
* 调用的是ReentrantLock 的解锁逻辑(ReentrantLock类)
*/
protected final boolean tryRelease(int releases) {
            //c=1
            int c = getState() - releases;
            //判断是否为同一个线程,不是就抛异常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                //独占线程设置为null
                setExclusiveOwnerThread(null);
            }
            //state的状态设置为0
            setState(c);
            //返回true释放锁成功
            return free;
        }
/*
* 唤醒所有线程
*/        
public final void signalAll() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            //获取头结点    
            Node first = firstWaiter;
            //头结点不为null
            if (first != null)
            	//条件队列转为同步等待队列
                doSignalAll(first);
}
/*
* 删除并转移所有节点
*/
 private void doSignalAll(Node first) {
 			//首位节点变为null	
            lastWaiter = firstWaiter = null;
            //条件等待队列出队
            do {
            	//第一个节点的下一个节点
                Node next = first.nextWaiter;
                //断开指针
                first.nextWaiter = null;
                //将节点从条件队列转移到同步队列方法调用
                transferForSignal(first);
                //设置下一个节点为第一个节点
                first = next;
            } while (first != null);
}
/*
* 将节点从条件队列转移到同步队列
*/
final boolean transferForSignal(Node node) {
        /*
         * If cannot change waitStatus, the node has been cancelled.
         */
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;
        /*
         * Splice onto queue and try to set waitStatus of predecessor to
         * indicate that thread is (probably) waiting. If cancelled or
         * attempt to set waitStatus fails, wake up to resync (in which
         * case the waitStatus can be transiently and harmlessly wrong).
         * 同步等待队列入队
         */
        Node p = enq(node);
        //等待状态为0
        int ws = p.waitStatus;
        //如果ws大于0直接唤醒 或者 把返回的线程p设置为-1(p为node的上一个节点)
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
        	//唤醒线程
            LockSupport.unpark(node.thread);
        return true;
 }
    /**
     * 同步等待队列(双向链表)
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
            	//第一次入队,创建新节点
                if (compareAndSetHead(new Node()))
                	//设置头、尾
                    tail = head;
            } else {
            	//前一个指针 prev
                node.prev = t;
                //设置后一个指针next
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    //最后一个节点的前一个node
                    return t;
                }
            }
        }
    }
 /*
 * 唤醒线程
 */   
 private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         * 获取waitStatus = -1
         */
        int ws = node.waitStatus;
        if (ws < 0)
        	//修改waitStatus  = 0
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        //找到下一个节点并唤醒线程
        if (s != null)
            LockSupport.unpark(s.thread);
    }

final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                //获取头结点,并且尝试获取锁tryAcquire ->nonfairTryAcquire()
                if (p == head && tryAcquire(arg)) {
                	/*
					* 出队同步等待队列逻辑
					*/
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
 /*
 * 获取锁,使用CAS方式获取锁
 */
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
					//设置为独占线程,获取锁成功
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

逻辑图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值