JUC.AQS

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 这篇文章是介绍前三种的

你可能感兴趣的:(JUC.AQS)