《Java并发编程实战》读书笔记——AQS、CountDownLatch和CyclicBarrier

1、AQS,AbstractQueuedSynchronizer,抽象的队列式同步器,是一个抽象类,用了模板方法模式。作为模板类,定义了多线程访问共享资源的框架。维护一个volatile int state代表共享资源和一个FIFO线程队列,state可以表示Semaphore的数值、ReentrantLock的重入次数、CountDownLatch的数量等,ReentrantReadWriteLock的state各用16位表示写/读锁的数量,写时,队列头部线程获得锁;读时,从头节点开始,第一个写线程之前的所有读线程获得锁,旧版本state也可以表示Future的状态,但FutureTask现在不用AQS实现了。

    自定义的同步器只需要实现共享资源state的获取与释放,包括tryAcquire(int arg),tryRelease(int arg),tryAcquireShared(int arg),tryReleaseShared(int arg)方法,至于队列维护(获取资源失败入队/资源被释放时唤醒线程出队)已经实现好了

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {

	// 等待队列的节点类,用于封装线程,会记录线程请求是独占还是共享
	static final class Node {

		static final Node SHARED = new Node();

		static final Node EXCLUSIVE = null;

		static final int CANCELLED = 1;

		static final int SIGNAL = -1;

		static final int CONDITION = -2;

		static final int PROPAGATE = -3;

		volatile int waitStatus;

		volatile Node prev;

		volatile Node next;

		volatile Thread thread;

		Node nextWaiter;

		final boolean isShared() {
			return nextWaiter == SHARED;
		}

		final Node predecessor() throws NullPointerException {
			Node p = prev;
			if (p == null)
				throw new NullPointerException();
			else
				return p;
		}

		Node() {
		}

		Node(Thread thread, Node mode) {
			this.nextWaiter = mode;
			this.thread = thread;
		}

		Node(Thread thread, int waitStatus) {
			this.waitStatus = waitStatus;
			this.thread = thread;
		}
	}

	// 等待队列的头结点
	private transient volatile Node head;

	// 等待队列的尾节点
	private transient volatile Node tail;

	// 资源的抽象
	private volatile int state;

	// 线程获取资源失败则进入等待队列,创建该线程的node,用到了经典的volatile变量+自旋CAS
	private Node enq(final Node node) {
		for (;;) {
			Node t = tail;
			if (t == null) { // Must initialize
				if (compareAndSetHead(new Node()))
					tail = head;
			} else {
				node.prev = t;
				if (compareAndSetTail(t, node)) {
					t.next = node;
					return t;
				}
			}
		}
	}

	// 子类定制tryAcquire(int arg)和tryRelease(int arg)等方法的实现
	protected boolean tryAcquire(int arg) {
		throw new UnsupportedOperationException();
	}

	protected boolean tryRelease(int arg) {
		throw new UnsupportedOperationException();
	}

	protected int tryAcquireShared(int arg) {
		throw new UnsupportedOperationException();
	}

	protected boolean tryReleaseShared(int arg) {
		throw new UnsupportedOperationException();
	}

	// 先tryAcquire(),如果失败则线程进入等待队列
	public final void acquire(int arg) {
		if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
			selfInterrupt();
	}

	public final void acquireInterruptibly(int arg) throws InterruptedException {
		// 如果线程被中断直接抛出异常
		if (Thread.interrupted())
			throw new InterruptedException();
		if (!tryAcquire(arg))
			doAcquireInterruptibly(arg);
	}

	// 定时获取资源
	public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
		if (Thread.interrupted())
			throw new InterruptedException();
		return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout);
	}

	// 唤醒队头节点的线程,出队
	public final boolean release(int arg) {
		if (tryRelease(arg)) {
			Node h = head;
			if (h != null && h.waitStatus != 0)
				unparkSuccessor(h);
			return true;
		}
		return false;
	}
}


2、CountDownLatch和CyclicBarrier

    都有参数为int count的构造器,CountDownLatch有countDown(),await()方法。await()方法会阻塞,直到调用count次countDown()。

    CyclicBarrier的await()方法等待其它线程到达,返回线程到达的序号。

    CountDownLatch不可重用,是1个或多个线程等待另外count(构造时指定)个线程,例如运动员在等待发令员开枪,这里多个运动员调用await()方法,发令员相当于new CountDownLatch(1),开枪就调用了countDown(),await()不再阻塞,运动员开始奔跑;CyclicBarrier可重用,是一组线程互相等待,就像运动员们等待所有的运动员都到达终点后,他们才开始庆祝。

    从源码上看看两者的区别,先看看CountDownLatch,用继承AQS的内部类实现,并未提供将资源恢复到count的方法,因此不可重用。

public class CountDownLatch {
	private static final class Sync extends AbstractQueuedSynchronizer {
		private static final long serialVersionUID = 4982264981922014374L;

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

		int getCount() {
			return getState();
		}
		
		// 重写了tryAcquireShared(int acquires),这样只有state == 0时才能获取资源
		protected int tryAcquireShared(int acquires) {
			return (getState() == 0) ? 1 : -1;
		}

		protected boolean tryReleaseShared(int releases) {
			// volatile + 自旋CAS
			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);
	}
	
	// state != 0时阻塞
	public void await() throws InterruptedException {
		sync.acquireSharedInterruptibly(1);
	}

	public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
		return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
	}

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

	public long getCount() {
		return sync.getCount();
	}

	public String toString() {
		return super.toString() + "[Count = " + sync.getCount() + "]";
	}
}

    再看看CyclicBarrier,用ReentrantLock实现线程安全,用一个count保存了构造时指定的parties,await()时parties不变,count--,重置栅栏时只要令count=parties即可,因此是可重入的

public class CyclicBarrier {

	// 用ReentrantLock保证线程安全
	private final ReentrantLock lock = new ReentrantLock();

	private final Condition trip = lock.newCondition();

	// 构造时指定,保持不变
	private final int parties;

	// 初始时==parties,每次await()减一
	private int count;

	// 重置count,重新开始新一轮的栅栏
	private void breakBarrier() {
		generation.broken = true;
		count = parties;
		trip.signalAll();
	}

	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();
			}
			// await()count减一,count表示未到达的线程数
			int index = --count;
			if (index == 0) {
				boolean ranAction = false;
				try {
					final Runnable command = barrierCommand;
					if (command != null)
						command.run();
					ranAction = true;
					nextGeneration();
					return 0;
				} finally {
					if (!ranAction)
						breakBarrier();
				}
			}

			for (;;) {
				try {
					if (!timed)
						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();
		}
	}
        // 构造时指定parties和count
	public CyclicBarrier(int parties, Runnable barrierAction) {
		if (parties <= 0)
			throw new IllegalArgumentException();
		this.parties = parties;
		this.count = parties;
		this.barrierCommand = barrierAction;
	}

	public CyclicBarrier(int parties) {
		this(parties, null);
	}

	public int await() throws InterruptedException, BrokenBarrierException {
		try {
			return dowait(false, 0L);
		} catch (TimeoutException toe) {
			throw new Error(toe);
		}
	}

	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();
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_39420024/article/details/80054738