首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Java多线程(7)之同步器基础:AQS框架深入分析(转)

2013-08-13 
Java多线程(七)之同步器基础:AQS框架深入分析(转)上图中,LOCK的实现类其实都是构建在AbstractQueuedSynchr

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
  1. //get时待用,只检查当前任务是否完成或者被Cancel,如果未完成并且没有被cancel,那么告诉AQS当前线程需要进入等待队列并且park住??protected?int?tryAcquireShared(int?ignore)?{??
  2. ?????return?innerIsDone()??1?:?-1;??}??
  3. ??//判定任务是否完成或者被Cancel??
  4. boolean?innerIsDone()?{??????return?ranOrCancelled(getState())?&&????runner?==?null;??
  5. }????
  6. //get时调用,对于CANCEL与其他异常进行抛错??V?innerGet(long?nanosTimeout)?throws?InterruptedException,?ExecutionException,?TimeoutException?{??
  7. ????if?(!tryAcquireSharedNanos(0,nanosTimeout))??????????throw?new?TimeoutException();??
  8. ????if?(getState()?==?CANCELLED)??????????throw?new?CancellationException();??
  9. ????if?(exception?!=?null)??????????throw?new?ExecutionException(exception);??
  10. ????return?result;??}??
  11. ??//任务的执行线程执行完毕调用(set(V?v))??
  12. void?innerSet(V?v)?{???????for?(;;)?{??
  13. ????????int?s?=?getState();??????????//如果线程任务已经执行完毕,那么直接返回(多线程执行任务?)??
  14. ????????if?(s?==?RAN)??????????????return;??
  15. ????????//如果被CANCEL了,那么释放等待线程,并且会抛错??????????if?(s?==?CANCELLED)?{??
  16. ????????????releaseShared(0);??????????????return;??
  17. ?????}??????????//如果成功设定任务状态为已完成,那么设定结果,unpark等待线程(调用get()方法而阻塞的线程),以及后续清理工作(一般由FutrueTask的子类实现)??
  18. ????????if?(compareAndSetState(s,?RAN))?{??????????????result?=?v;??
  19. ????????????releaseShared(0);??????????????done();??
  20. ????????????return;???????}??
  21. ?}??}??

?

以上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

热点排行