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