Java并发——AQS源码解析

本文深入探讨了AQS(AbstractQueuedSynchronizer)的工作原理,它是Java并发库的基础。AQS通过状态变量state管理和维护锁的持有状态,并使用CLH锁队列实现。文章详细分析了AQS的内部类Node、独占式和共享式同步状态的获取与释放,以及如何响应中断和超时。通过对AQS源码的学习,有助于理解各种锁的机制和问题排查。
摘要由CSDN通过智能技术生成

本文通过总结源码学习,来分析了解下AQS的工作原理

AQS是juc包锁实现的基础框架,研究juc包源码之前,AQS是必经之路
虽然说,平时项目中,我们几乎不会有自己去继承aqs实现锁的需要,但是通过源码了解aqs的机制和原理,有助于我们加深对各种锁的理解,以及出现问题时排查的思路

AbstractQueuedSynchronizer抽象队列同步器,CLH 锁

The wait queue is a variant of a “CLH” (Craig, Landin, and Hagersten) lock queue. CLH locks are normally used for spinlocks. We instead use them for blocking synchronizers, but use the same basic tactic of holding some of the control information about a thread in the predecessor of its node. A “status” field in each node keeps track of whether a thread should block. A node is signalled when its predecessor releases.

双向FIFO等待队列,自旋锁,使用队列结点对象Node包装要获取锁的线程
AQS通过一个状态变量state,来标志当前线程持有锁的状态。
state = 0时代表没有持有锁,> 0 代表持有锁。
当队列中一个结点释放锁时,会唤醒后继阻塞的线程

内部类Node
static final class Node {
    /** 共享模式的Node */
    static final Node SHARED = new Node();
    /** 独占模式的Node */
    static final Node EXCLUSIVE = null;

    /** waitStatus value to indicate thread has cancelled */
    static final int CANCELLED =  1;
    /** waitStatus value to indicate successor's thread needs unparking */
    static final int SIGNAL    = -1;
    /** waitStatus value to indicate thread is waiting on condition */
    static final int CONDITION = -2;
    /**
     * waitStatus value to indicate the next acquireShared should
     * unconditionally propagate
     */
    static final int PROPAGATE = -3;

    volatile int waitStatus;

    volatile Node prev;

    volatile Node next;

    // 等待队列中当前结点线程
    volatile Thread thread;

    Node nextWaiter;

    /**
     * Returns true if node is waiting in shared mode.
     */
    final boolean isShared() {
        return nextWaiter == SHARED;
    }

    // 获取前驱结点
    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;
    }
}

如下图就是aqs同步队列中的一个节点结构,它有两个分别指向前后节点的指针,包含了当前线程thread,以及节点的状态waitStatus
Node

waitStatus解释
其实关于waitStatus,有点不好理解的是SIGNAL这个状态
我们先来看一下源码中是如何解释的

/** waitStatus value to indicate successor's thread needs unparking */
static final int SIGNAL    = -1;

    /**
     * Status field, taking on only the values:
     *   SIGNAL:     The successor of this node is (or will soon be)
     *               blocked (via park), so the current node must
     *               unpark its successor when it releases or
     *               cancels. To avoid races, acquire methods must
     *               first indicate they need a signal,
     *               then retry the atomic acquire, and then,
     *               on failure, block.
     */
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值