CyclicBarrier同步屏障源码

CyclicBarrier工具类的特点

CyclicBarrier采用一种屏障的方式来控制线程,让所有线程停在某一点,已到的等最后到才完事。先到的线程将处于阻塞的状态。

属性

    /** 定义一个排他锁 */  
    private final ReentrantLock lock = new ReentrantLock();  

    /** 创建一个等待队列 */  
    private final Condition trip = lock.newCondition();  

    /** 等待线程的数量 */  
    private final int parties;  

    /* 当栅栏被释放后执行的线程 */  
    private final Runnable barrierCommand;  

    /** 当前的一代线程组 */  
    private Generation generation = new Generation();  
  
    /**  
     * 在当前一代线程组中等待线程的数量从parties减到0。  
     * count值是在创建新的一代线程时被重置。  
     */  
    private int count;  

说明:线程组是指启动此 barrier 的参与者(所有线程)被叫做线程组。

内部类

   /**  
    * 一个栅栏代表了一代线程组,栅栏被重置或者跳闸时,一代线程组发生改变。  
    * 如果一代线程组被实例化了,那么这个栅栏被打破的标志位为false。  
    */  
   private static class Generation {  
       boolean broken = false;  
   }  

构造器

    /**  
     * 栅栏构造器  
     * 输入参数为线程组中的等待线程数、最后执行的线程  
     */  
    public CyclicBarrier(int parties, Runnable barrierAction) {  
    //如果等待线程数不大于0,那么就抛出非法参数异常  
        if (parties <= 0) throw new IllegalArgumentException();  
    //初始化等待线程数  
        this.parties = parties;  
    //初始化操作线程数  
        this.count = parties;  
    //初始化栅栏破坏后,最后执行的线程  
        this.barrierCommand = barrierAction;  
    }  
    /**  
     * 栅栏构造器  
     * 就是没有最后执行的线程的栅栏  
     */  
    public CyclicBarrier(int parties) {  
        this(parties, null);  
    }  

核心实现

breakBarrier方法:设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程

    /**  
     * 设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程  
     * 在持有锁的时候,才可以调用该方法。  
     */  
    private void breakBarrier() {  
        //设置一代线程组对应的栅栏状态为true(意思就是栅栏被破坏了)  
        generation.broken = true;  
        //重新设置计数count值  
        count = parties;  
        //唤醒所有等待的线程  
        trip.signalAll();  
    }  

nextGeneration方法:重新设置下一代线程组

    /**  
     * 重新设置下一代线程组  
     * 当栅栏跳闸时,就是线程都到达屏障时,就更新同步状态,然后唤醒所有等待的线程。  
     * 但是只能在持有锁时才可以调用该方法。  
     */  
    private void nextGeneration() {  
        //唤醒所有等待的线程   
        trip.signalAll();  
        //重新设置计数count值  
        count = parties;  
        //重新创建一代线程组  
        generation = new Generation();  
    }  

doAwait方法:主要用于限时等待和非限时等待

    /**  
     * 等待通用方法  
     */  
    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();  
            }  
           //获取一代线程组中等待线程的数量-1  
           int index = --count;  
           //如果达到跳闸的条件  
           if (index == 0) {  // tripped  
               boolean ranAction = false;  
               try {  
                   //获取跳闸后执行的线程  
                   final Runnable command = barrierCommand;  
                   //如果该线程不为空,那么就执行最后的线程  
                   if (command != null)  
                       command.run();  
                   //将标记位设置为true  
                   ranAction = true;  
                   //重新设置下一代线程组  
                   nextGeneration();  
                   return 0;  
               } finally {  
                   if (!ranAction)  
                       breakBarrier();  
               }  
           }  
  
            // 死循环,除非出现栅栏破坏了、线程中断、超时情况才结束循环  
            for (;;) {  
                try {  
            /* timed时间标志位  
             * 如果timed为false,那么线程等待队列将一直被挂起,线程一直处于等待状态。  
             */  
                    if (!timed)  
                        trip.await();  
                    else if (nanos > 0L)  
                       /**  
                        * 如果时间标志位timed为true  
                        * 如果等待时间大于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();  
        }  
    }

方法

    /**  
     * 获取启动此 barrier 的参与者数目  
     */  
    public int getParties() {  
        return parties;  
    }  
  
    /**  
     * 在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。  
     */  
    public int await(long timeout, TimeUnit unit)  
        throws InterruptedException,  
               BrokenBarrierException,  
               TimeoutException {  
        return dowait(true, unit.toNanos(timeout));  
    }  
  
    /**  
     * 查看屏障是否处于破坏状态  
     */  
    public boolean isBroken() {  
        //获取当前的排它锁  
        final ReentrantLock lock = this.lock;  
        //获取锁  
        lock.lock();  
        try {  
            //返回当前这一代线程组中的状态  
            return generation.broken;  
        } finally {  
            //释放锁  
            lock.unlock();  
        }  
    }  
  
    /**  
     * 将屏障设置为初始化的状态  
     */  
    public void reset() {  
        //获取排他锁  
        final ReentrantLock lock = this.lock;  
        //获取锁  
        lock.lock();  
        try {  
            //设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程  
            breakBarrier();   
            //重新设置下一代线程组  
            nextGeneration();   
        } finally {  
            //释放锁  
            lock.unlock();  
        }  
    }  
  
    /**  
     * 获取当前屏障处等待的线程数  
     */  
    public int getNumberWaiting() {  
        //获取排他锁  
        final ReentrantLock lock = this.lock;  
        //获取锁  
        lock.lock();  
        try {  
            //总等待线程数减去当前剩余没到达的线程数  
            return parties - count;  
        } finally {  
            //释放锁  
            lock.unlock();  
        }  
    }  

---------------------------该源码为jdk1.7版本的

你可能感兴趣的:(CyclicBarrier同步屏障源码)