浅析J.U.C的AQS(一):CountDownLatch

来源:互联网 发布:网络慈善活动策划方案 编辑:程序博客网 时间:2024/06/04 23:18

AQS全称AbstractQueuedSynchronizer,顾名思义,是用于同步的队列抽象类。

之所以想浅析AQS,是因为其在J.U.C中颇为重要。事实上,FutureTaskCountDownLatchLock、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                 @Override13                 public void run()14                 {15                     try16                     {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         try30         {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是否为010             return (getState() == 0) ? 1 : -1;11         }12 13         protected boolean tryReleaseShared(int releases) {14             // count--,返回count是否等于015             for (;;) {16                 int c = getState();17                 if (c == 0)18                     return false;19                 int nextc = c-1;20                 //CAS操作,设置c为c-121                 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到底是如何实现的了?

请期待下一篇博文。

原创粉丝点击