Java 5 中的诸如 ReentrantLock、Semaphore、FutureTask 等并发类都应用了前一篇所提到的 CAS。但是它们也都不是直接使用 CAS,而是通过 AbstractQueuedSynchronizer 来实现的。虽然 Java 5 中的并发类对于绝大多数的场景来说已经够用了,但是了解 AQS 对于理解这些并发类的实现原理是不无益处的,而且还可以使你在已有的并发类无法满足需要的时候可以有机会一显身手。
State
在 AQS 中有一个 int 类型的 volatile 变量 state,使用 AQS 的类可以自定义 state 对其的含义。例如,ReentrantLock 用 0 表示没有线程获取锁,大于 0 则表示重入锁的重入次数;Semaphore 用来表示许可数量;FutureTask 用来表示任务状态,例如运行中、已完成等。
在扩展 AQS 时,子类需要根据自己的需求在诸如 tryAcquire 方法中使用 compareAndSetState 方法设置相应的状态值。
独占模式和共享模式
处于独占模式下时,其他线程试图获取该锁将无法取得成功。在共享模式下,多个线程获取某个锁可能(但不是一定)会获得成功。此类并不“了解”这些不同,除了机械地意识到当在共享模式下成功获取某一锁时,下一个等待线程(如果存在)也必须确定自己是否可以成功获取该锁。
上面这段话是摘自 Java 6 API。这段话可能不太好了解。简单地说,独占模式就是只能有一个线程获取锁(同步器),分享模式下则可以有多个线程成功获取锁(同步器),但也可以不能。
其实 AQS 并不知道这些区别,它只是提供了相应的方法供子类 override,并由子类选择使用哪种模式。
模式的选择也很简单,AQS 提供了两组方法:
- tryAcquire(int)
- tryRelease(int)
- tryAcquireShared(int)
- tryReleaseShared(int)
从名字便可看出,前两个方法对应于独占模式,后两个对于分享模式。这些方法又分别被 acquire(int arg)、acquireShared(int arg) 等方法调用。而使用 AQS 的类可以通过选择不同的方法来选择使用何种模式。
转载 http://my.oschina.net/lifany/blog/134967