美文网首页
aqs-队列和同步状态

aqs-队列和同步状态

作者: 兴浩 | 来源:发表于2018-06-16 21:54 被阅读6次

参考:
http://9056c4f4.wiz03.com/share/s/2glIjQ0JcAZG22OnBj0NaD4u3LNmdz1RAkzX2dbQHr00enD2

上面文章基本涵盖了很多的基本数据结果概念

1.Node数据结构
2.同步队列结构图

重点关注acquire方法模板中,添加Node的实现

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

1. addWaiter

    /**
     * Creates and enqueues node for current thread and given mode.
     *
     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
     * @return the new node
     */
    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;
    }

    /**
     * Inserts node into queue, initializing if necessary. See picture above.
     * @param node the node to insert
     * @return node's predecessor
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

addWaiter方法和enq有部分代码是比较像的,
初始化时,会调用enq方法,初始化head和tail,并将添加的Node节点添加到队尾
如果有队尾(即有节点),则快速结束

2. acquireQueued方法

2.1出列

    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);
        }
    }

参考图片:


这里完成了一个出列的过程

2.2 同步状态的线程阻塞
parkAndCheckInterrupt在入列的时候,使用LockSupport阻塞线程

    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

3.锁释放

锁释放也是先调用tryRelease,将state重置为0,然后调用unparkSuccessor方法

    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

unparkSuccessor方法查找当前node的next节点,并调用LockSupport的unpark方法,唤醒线程

    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }

参考:

【死磕Java并发】—–J.U.C之AQS:CLH同步队列

【死磕Java并发】—–J.U.C之AQS:同步状态的获取与释放

相关文章

  • aqs-队列和同步状态

    参考:http://9056c4f4.wiz03.com/share/s/2glIjQ0JcAZG22OnBj0N...

  • AQS(队列同步器)CLH中的节点入队源码(二)

    根据目前对队列同步器的理解,先把目前对AQS-队列同步器认识记录一下。然后根据源码的注释,一点点进行解析 首先说明...

  • 并发编程05--Java中的锁(Lock接口和队列同步器)

    Java中的锁Lock接口队列同步器队列同步器的接口与示例队列同步器的实现分析同步队列独占式同步状态获取与释放共享...

  • AQS同步队列与条件队列的关系

    一、关系 同步队列节点来源: 1、同步队列依赖一个双向链表来完成同步状态的管理,当前线程获取同步状态失败 后,同步...

  • java.util.concurrent.locks.Abstr

    什么是队列同步器? AQS队列同步器作为构建锁或者其他同步组件的基础框架。使用int型的成员变量来表示同步的状态,...

  • 第5章 Java的锁

    基本概念: 锁:控制多线程并发访问资源;队列同步器:管理同步状态,实现锁;同步状态:同步器的操作对象,int类型;...

  • 多线程的运用

    同步串行队列 同步并发队列 异步串行队列 异步并发队列 队列组 栅栏 队列组和栅栏的组合 信号量 死锁主线程 分析...

  • GCD详解

    一 使用步骤 创建队列(串行队列或并发队列) 调用函数(同步或异步) 二 重要概念 1,同步和异步 同步或异步最大...

  • GCD的几种创建方式及基本使用

    同步函数 同步函数+主队列 同步函数+串行队列 同步函数+并发队列 异步函数 异步函数+主队列 异步函数+串行队列...

  • GCD基础总结一

    上代码~ 同步串行队列 同步并行队列 异步串行队列 异步并行队列 主队列同步 会卡住 主队列异步

网友评论

      本文标题:aqs-队列和同步状态

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