AQS : AbstractQueuedSynchronizer
AQS内部维护一个FIFO队列来完成获取锁线程的排队工作。底层是一个双向链表(队列的一种实现)
-
使用node实现FIFO队列,可以用来构建锁或其他同步装置的基础框架
-
利用了一个int类型表示状态:state (表示获取锁的线程数)
-
使用方法是继承
-
子类通过继承并实现方法管理其状态(acquire和release)方法的操纵。
-
可同时实现排他锁和共享锁模式(独占,共享):他的所有子类都是只实现了其中的一种api,不会同时现实两种
过程: 未获取到锁的线程会利用CAS操作线程安全的加入到队列尾部,队列头部的线程是获取到同步状态(锁)的线程。队列头部的线程在完成任务释放锁后会唤醒它的后继,后继会在获取锁成功后把自己设置为头节点。(CAS+死循环)
多个线程都通过CAS+死循环的方式来对队列进行修改,每次能够保证只有一个成功,如果是N个线程,那每个线程最多loop N次 。
由于state的更新只影响了队列头部一个线程,避免了群羊效应
主要方法:
-
isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
-
tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
-
tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
-
tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
-
tryReleaseShared(int):共享方式。尝试释放资源,成功则返回true,失败则返回false。
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
AQS的常用子类:
-
CountDownLatch
-
Semaphore
-
CyclicBarrier
-
ReentrantLock
-
Condition
-
FutureTask
http://www.importnew.com/21889.html 这篇文章是介绍前三种的
网友评论