AQS全称AbstractQueuedSynchronizer,顾名思义,是用于同步的队列抽象类。
之所以想浅析AQS,是因为其在J.U.C中颇为重要。事实上,FutureTask、CountDownLatch、Lock、Semaphore和CyclicBarrier都是通过派生AbstractQueuedSynchronizer来实现功能。baidu
实际上FutureTask等类内部调用AQS的逻辑并不复杂,以CountDownLatch为例:
1 public class CountDownLatchTest 2 { 3 //简单的CountDownLatch实例,5个线程都执行完毕后才会输出最后一句话 4 private final static CountDownLatch CDL_TEST = new CountDownLatch(5); 5 6 public static void main(final String[] args) 7 { 8 for (int i = 0; i < 5; i++) 9 { 10 new Thread() 11 { 12 @Override 13 public void run() 14 { 15 try 16 { 17 Thread.sleep(5000); 18 } 19 catch (InterruptedException e) 20 { 21 e.printStackTrace(); 22 } 23 System.out.println(this.getName() + " 结束啦"); 24 CDL_TEST.countDown(); 25 } 26 }.start(); 27 } 28 29 try 30 { 31 CDL_TEST.await(); 32 } 33 catch (InterruptedException e) 34 { 35 e.printStackTrace(); 36 } 37 System.out.println("终于可以运行了"); 38 }
CountDownLatch的核心函数是await和countDown。这两个函数的源码实现非常简单,就1行:
1 public void await() throws InterruptedException { 2 sync.acquireSharedInterruptibly(1); 3 } 4 5 public void countDown() { 6 sync.releaseShared(1); 7 }
那么这个sync内部到底实现了什么了,直接看源码:
1 //sync是AQS的派生类 2 private static final class Sync extends AbstractQueuedSynchronizer { 3 Sync(int count) { 4 //设置count,在本例中是5 5 setState(count); 6 } 7 8 protected int tryAcquireShared(int acquires) { 9 //判断state是否为0 10 return (getState() == 0) ? 1 : -1; 11 } 12 13 protected boolean tryReleaseShared(int releases) { 14 // count--,返回count是否等于0 15 for (;;) { 16 int c = getState(); 17 if (c == 0) 18 return false; 19 int nextc = c-1; 20 //CAS操作,设置c为c-1 21 if (compareAndSetState(c, nextc)) 22 return nextc == 0; 23 } 24 } 25 }
源码看到现在,CountDownLatchTest是如何实现5个线程都执行完毕才输出最后一句话的内部实现就很明了了:
1.初始化CDL_TEST 的state为5;
2.主线程执行至31行CDL_TEST.await(),此时state!=0,因此阻塞住;
3.5个副线程陆续执行到24行CDL_TEST.countDown(),通过CAS修改state的值。
4.当state为0时,唤醒主线程,主线程继续执行,输出了最后一段话。
其中,初始化state、判断state状态和修改state的值是Sync自行实现。而阻塞和唤醒线程则是AQS内部实现的。
那么这个AQS到底是如何实现的了?
请期待下一篇博文。