Java多线程(七)之同步器基础:AQS框架深入分析(转)
上图中,LOCK的实现类其实都是构建在AbstractQueuedSynchronizer上,为何图中没有用UML线表示呢,这是每个Lock实现 类都持有自己内部类Sync的实例,而这个Sync就是继承AbstractQueuedSynchronizer(AQS)。为何要实现不同的Sync 呢?这和每种Lock用途相关。另外还有AQS的State机制。下文会举例说明不同同步器内的Sync与state实现。
?
?
二、AQS框架如何构建同步器?0、同步器的基本功能?一个同步器至少需要包含两个功能:
1.???????获取同步状态
如果允许,则获取锁,如果不允许就阻塞线程,直到同步状态允许获取。
2.???????释放同步状态
修改同步状态,并且唤醒等待线程。
根据作者论文,?aqs?同步机制同时考虑了如下需求:
1.???????独占锁和共享锁两种机制。
2.???????线程阻塞后,如果需要取消,需要支持中断。
3.???????线程阻塞后,如果有超时要求,应该支持超时后中断的机制。
?
1、同步状态的获取与释放?
AQS实现了一个同步器的基本结构,下面以独占锁与共享锁分开讨论,来说明AQS怎样实现获取、释放同步状态。
?
1.1、独占模式?独占获取:?tryAcquire?本身不会阻塞线程,如果返回?true?成功就继续,如果返回?false?那么就阻塞线程并加入阻塞队列。
?
??
[java] view plaincopy?
以上4个AQS的使用是比较典型,然而有个问题就 是这些状态存在哪里呢?并且是可以计数的。从以上4个example,我们可以很快得到答案,AQS提供给了子类一个int state属性。并且暴露给子类getState()和setState()两个方法(protected)。这样就为上述状态解决了存储问 题,RetrantLock可以将这个state用于存储当前线程的重进入次数,Semaphore可以用这个state存储许可 数,CountDownLatch则可以存储需要被countDown的次数,而Future则可以存储当前任务的执行状态 (RUNING,RAN,CANCELL)。其他的Synchronizer存储他们的一些状态。
AQS留给实现者的方法主要有5个方法,其中 tryAcquire,tryRelease和isHeldExclusively三个方法为需要独占形式获取的synchronizer实现的,比如线 程独占ReetranLock的Sync,而tryAcquireShared和tryReleasedShared为需要共享形式获取的 synchronizer实现。
ReentrantLock内部Sync类实现的 是tryAcquire,tryRelease, isHeldExclusively三个方法(因为获取锁的公平性问题,tryAcquire由继承该Sync类的内部类FairSync和 NonfairSync实现)Semaphore内部类Sync则实现了tryAcquireShared和tryReleasedShared(与 CountDownLatch相似,因为公平性问题,tryAcquireShared由其内部类FairSync和NonfairSync实现)。 CountDownLatch内部类Sync实现了tryAcquireShared和tryReleasedShared。FutureTask内部类 Sync也实现了tryAcquireShared和tryReleasedShared。
参考内容来源:
【java并发】juc高级锁机制探讨
http://singleant.iteye.com/blog/1418580
Java并发同步器AQS(AbstractQueuedSynchronizer)学习笔记(1)
http://my.oschina.net/zavakid/blog/84882
Java并发同步器AQS(AbstractQueuedSynchronizer)学习笔记(2)
http://my.oschina.net/zavakid/blog/85008
JAVA LOCK代码浅析
http://rdc.taobao.com/team/jm/archives/414
java thread 之AQS
http://www.cnblogs.com/nod0620/archive/2012/07/23/2605504.html