同步计数器CountDownLatch 和CyclicBarrier

CountDownLatch ,把一个工作分给5个人,5个线程都执行完了,调用countDown,给计数器减数,而主线程await,等数为零,主线程继续往下执行,即5条线程都完成才算工作完成。

内部很简单,还是继承AQS,把设置的数量赋值给state,countDown就减state,await想必挂起线程和解放线程。

CyclicBarrier 这么打比方,5个线程,每个人的工作分成两部分,完成第一部分后,需要确保5个人都完成了第一部分,大家才能各自进行第二部分。同时CyclicBarrier  可以设置一个主任务,在5个人的第一部分都执行完之后,这个主任务就会执行

CountDownLatch 是一个线程(例子中是主线程)等待其他线程执行完毕后,才能执行。

CyclicBarrier 是多个线程互相等待对方执行到指定的那一步,然后这些线程才能继续执行

一.CountDownLatch

1.例子

public class TestCountDown {

	public static void main(String[] args) throws InterruptedException {
		CountDownLatch latch = new CountDownLatch(4);
		Work w1 = new Work(latch);
		Work w2 = new Work(latch);
		Work w3 = new Work(latch);
		w1.start();
		w2.start();
		w3.start();
		latch.await();
		System.out.println("latch要等计数器为0,await方法才能释放");
	}
	
	static class Work extends Thread{
		
		private CountDownLatch latch;
		
		@Override
		public void run() {
			System.out.println(Thread.currentThread().getName()+"正在工作");
			latch.countDown();
		}

		public Work(CountDownLatch latch) {
			super();
			this.latch = latch;
		}
		
	}
}

主线程只有等三个线程都执行完,计数器为零后,await方法才释放,才执行

如果改为CountDownLatch latch = new CountDownLatch(4);

会发现主线程一直堵塞,因为计数器永远无法到0

2.应用场景

开五个线程去上传或下载,只有五个线程都成功才算成功

3.源码

new CountDownLatch(4);数量其实是Sync的state

public class CountDownLatch {
    /**
     * Synchronization control For CountDownLatch.
     * Uses AQS state to represent count.
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

    private final Sync sync;

    
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

countDown其实就是在对state减一,到0时就不能减了

   public void countDown() {
        sync.releaseShared(1);
    }

    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }

await应该是计算state是否=0,不等于就堵塞

   public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

  private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

二.CyclicBarrier

1.例子

public class TestCyclicBarrier {

	public static void main(String[] args) {
		CyclicBarrier barrier = new CyclicBarrier(3,new TotalTask());
		Work w1 = new Work(barrier);
		Work w2 = new Work(barrier);
		Work w3 = new Work(barrier);
		w1.start();w2.start();w3.start();
		System.out.println("z主线程");
	}
	
	static class TotalTask extends Thread{
		@Override
		public void run() {
			System.out.println("所有任务的第一部分都执行完,总任务就会执行");
		}
	}
	
	static class Work extends Thread{
		
		private CyclicBarrier barrier;
		public Work(CyclicBarrier barrier) {
			this.barrier = barrier;
		}

		@Override
		public void run() {
			System.out.println(Thread.currentThread().getName()+"执行工作的第一部分");
			try {
				barrier.await();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"执行工作的第二部分");
		}
	}
}

猜你喜欢

转载自blog.csdn.net/u014203449/article/details/83959092