JUC.AQS

作者: 小明17 | 来源:发表于2019-06-03 18:47 被阅读0次

    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

        本文链接:https://www.haomeiwen.com/subject/sgdhxctx.html