AQS (AbstractQueuedSynchronizer) 详解

AQS,全称 AbstractQueuedSynchronizer,是JUC框架中最重要的类,是J.U.C 中绝大部分的工具类的基础,也是必经之路。

使用层面上AQS有两大功能实现:独占和共享

    独占锁,每次只能有一个线程持有锁,比如ReentrantLock就是以独占方式实现的互斥锁 。

    共享锁 ,允许多个线程同时获取锁 ,并发访问共享资源 , 比 如ReentrantReadWriteLock。

    AQS 队列内部维护的是一个 FIFO 的双向链表,这种结构的特点是每个数据结构都有两个指针,分别指向直接的后继节点和直接前驱节点。所以双向链表可以从任意一个节点开始很方便的访问前驱和后继。每个 Node 其实是由线程封装,当线程争抢锁失败后会封装成 Node 加入到 ASQ 队列中去;当获取锁的线程释放锁以后,会从队列中唤醒一个阻塞的节点(线程)。

 

Node节点(源码)

 

  static final class Node {
        static final Node SHARED = new Node(); //共享模式的标记
        static final Node EXCLUSIVE = null;//独占模式的标识
        static final int CANCELLED =  1;//线程被取消
        static final int SIGNAL    = -1;//标志着后继线程(即队列中此节点之后的节点)需要被阻塞.(用于独占锁)
        static final int CONDITION = -2;//标志着线程在Condition条件上等待阻塞.(用于Condition的await等待)
        static final int PROPAGATE = -3;//下一个acquireShared方法线程应该被允许。(用于共享锁)  
        
        volatile int waitStatus;//状态

        volatile Node prev; //前置节点

        volatile Node next;//后置节点

        volatile Thread thread;//当前线程

        Node nextWaiter;//指向Condition队列

    final boolean isShared() {//共享
        return nextWaiter == SHARED;
    }

    final Node predecessor() throws NullPointerException {//获得当前节点的前置节点
        Node p = prev;
        if (p == null)
            throw new NullPointerException();
        else
            return p;
    }

    //构造方法
    Node() {   
    }
    // 使用在addWaiter方法中
    Node(Thread thread, Node mode) {     
        this.nextWaiter = mode;
        this.thread = thread;
    }
    //使用在Condition条件中
    Node(Thread thread, int waitStatus) { 
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

总结:获取锁和释放锁的过程就是Node的变化过程

具体如果使用见ReentrantLock的源码分析:https://www.cnblogs.com/dyg0826/p/10467514.html

 

 另外:整个JUC包中很多地方用到了 cas 无锁化机制,见手绘图

 

posted @ 2019-06-18 16:29  Don'tYouSee  阅读(206)  评论(0)    收藏  举报