AQS详解

1.AQS是什么?

AQS是AbstractQueuedSynchronizer的简称,它是一个java的底层同步工具类,用一个int类型的变量表示同步状态,并且提供了一系列的CAS操作来管理这个同步状态

2.同步队列

   同步队列是AQS中 很重要的一部分,它是一个双端队列,遵循FIFO原则,主要的作用是用来存放在锁上阻塞的线程,当一个线程尝试获取锁的时候,如果已经被占用的话,那么当前线程会构造出一个Node节点,放到同步等待队列的尾部,队列的头结点是成功获取锁的节点,当头结点释放锁的时候会唤醒下一个节点去获取锁

AbstractQueuedSynchronizer中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;
        
        static final int PROPAGATE = -3;

        /**
         * 等待的状态
         */
        volatile int waitStatus;

        /**
         * 当前节点的前驱节点
         */
        volatile Node prev;

        /**
         * 当前节点的下一个节点
         */
        volatile Node next;

        /**
         * 当前节点的线程
         */
        volatile Thread thread;

        /**
         * 等待队列中的下一个节点
         */
        Node nextWaiter;

        /**
         * 返回这个节点的等地状态是否是共享状态
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /**
         * 节点判空
         *
         * @return the predecessor of this node
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker
        }

        Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

  AbstractQueuedSynchronizer中 addWaiter方法详解

 /**
  * 创建一个等待队列
 */
private Node addWaiter(Node mode) {
        // 以给定的模式为当前线程创建一个Node节点信息
        Node node = new Node(Thread.currentThread(), mode);
        // 尾节点
        Node pred = tail;
        // 如果尾节点不为null,则设置当前节点的前驱节点为尾节点,在利用cas操作设置尾节点
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        // 如果尾节点为null的话则将当前node节点设置为尾节点
        enq(node);
        return node;
    }

    /**
     * 将节点安全的插入队列,必要时初始化队列
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            // 如果尾节点是null的话必须初始化等待队列
            if (t == null) { // Must initialize
                // 创建一个等待队列出来,利用CAS操作设置头结点,头尾相连
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

3.独占式获取锁

    /**
     * 独占式获取锁的方法
     */
    public final void acquire(int arg) {
        // 尝试获取锁,如果没获取到,就加入到等待同步队列中
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }


    /**
     * 首先判断其前驱节点释放为头节点&是否成功获取同步状态,两个条件都成立,则将当前线程的节点设
        置为头节点,如果不是则利用LockSuport.park()方法将当前线程挂起,等待前驱节点的呼唤
     */
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

4.独占式释放锁分析

    /**
     * 释放锁
     */
    public final boolean release(int arg) {
        // 尝试释放锁
        if (tryRelease(arg)) {
            Node h = head;
            // 释放成功的话则判断头结点是否不等于null,等待状态是否不等于0
            if (h != null && h.waitStatus != 0)
                // 调用本地方法唤醒下一个节点
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

5.共享式获取锁 释放锁和独占式雷同,不一样的地方是头结点释放锁的话是唤醒后面所有的等待节点

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值