编程语言
首页 > 编程语言> > AQS源码浅析

AQS源码浅析

作者:互联网

一、AQS简介

AbstractQueuedSynchronizer 抽象队列同步器。简称AQS,同时拥有 同步队列 与 等待队列

二、源码浅析

  1. 同步队列
        线程调用了lock 方法,首先调用 acquire 方法请求锁,acquire 里面首先将现场节点封装Node 加入到同步队列的队尾,然后 在 acquireQueued 的循环里面,while 的判断 是不是head ,是则直接return 说明获取到锁,如果不是 则 调用了 park 方法阻塞,但是while 循环的跳出只能是 当前node 是head 。( 但是前面也说了 head 移除之后会 unpark 后面的结点,并且将后面的setHead) ,所以对于每个在抽象队列同步器的同步队列里面的Node,都是阻塞的,但是同步器每次acquire都会有一个acquireQueued ,相当于每个Node 都会 循环的请求,但是循环是同步器发出的,类似于一个“自旋”,这个自旋是 同步器控制的,线程还是阻塞的。
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

  2. 等待队列

        调用 await 方法,进入condition的等待队列,释放锁,进入一个 while 循环,只有当线程回到同步队列或者被中断才可以跳出while,while里面 park 掉线程 ----- 在 condition调用 signal 之后,该condition上面的节点的 firstWaiter 首先加入到 同步队列尾部 , 会 unpark 线程,退出 while 之后,又会进入 acquireQueued 的循环里面,同样存在之前的逻辑。

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    Node node = addConditionWaiter();
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    while (!isOnSyncQueue(node)) {
        LockSupport.park(this);
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
            break;
    }
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
        interruptMode = REINTERRUPT;
    if (node.nextWaiter != null) // clean up if cancelled
        unlinkCancelledWaiters();
    if (interruptMode != 0)
        reportInterruptAfterWait(interruptMode);
}

  3. 总结

三、工具类

定义了一系列的公有静态方法,用于 阻塞&&唤醒 一个线程。 LockSupport 中的park 与 unpark 等方法,最终都是调用的 Unsafe 类中的方法,而 Unsafe 类中提供的是一系列的硬件级别的原子操作 ,有点类似于 汇编级别或者机器码级别 指令一样

 

转载请注明地址:https://www.cnblogs.com/handsomecui/p/14253284.html

标签:node,调用,AQS,队列,同步器,while,源码,线程,浅析
来源: https://www.cnblogs.com/handsomecui/p/14253284.html