1. interrupt() 线程标记为中断,抛异常.
  2. isInterrupt() 判断线程是否中断,并且重置为false.
  3. isInterrupted() 判断线程是否中断.

    为什么需要虚拟头结点(来自路神笔记)

    tf:第一个给lock加锁的线程
    如果是第一个线程tf,那么和队列无关,线程直接持有锁。并且也不会初始化队列,如果接下来的线程都是交替执行,那么永远和AQS队列无关,都是直接线程持有锁,如果发生了竞争,比如tf持有锁的过程中T2来lock,那么这个时候就会初始化AQS,初始化AQS的时候会在队列的头部虚拟一个Thread为NULL的Node,因为队列当中的head永远是持有锁的那个node(除了第一次会虚拟一个,其他时候都是持有锁的那个线程锁封装的node),现在第一次的时候持有锁的是tf而tf不在队列当中所以虚拟了一个node节点,队列当中的除了head之外的所有的node都在park,当tf释放锁之后unpark某个(基本是队列当中的第二个,为什么是第二个呢?前面说过head永远是持有锁的那个node,当有时候也不会是第二个,比如第二个被cancel之后,至于为什么会被cancel,不在我们讨论范围之内,cancel的条件很苛刻,基本不会发生)node之后,node被唤醒,假设node是t2,那么这个时候会首先把t2变成head(sethead),在sethead方法里面会把t2代表的node设置为head,并且把node的Thread设置为null,为什么需要设置null?其实原因很简单,现在t2已经拿到锁了,node就不要排队了,那么node对Thread的引用就没有意义了。所以队列的head里面的Thread永远为null

    公平锁和非公平锁区别

    上来就尝试获取锁,失败就走公平锁的流程

    公平锁加锁流程

    AQS 结构为 headNode:头节点,tailNode:尾结点,state:加锁次数,exclusiveOwnerThread:当前获取锁的线程;
    node结构:pre,next,waitState:节点等待状态(主要类型 -1:后面有节点等待状态,0:正常等待状态,1:取消获取锁 ),node当前线程。

  4. lock 调用 acquire()方法,AQS 的 acquire()分3个方法 tryAcquire()尝试加锁,aqurieQueued()加锁失败,进入队列,等待队列被唤醒,selfInterrupt()重置interrupt()作用不大。

  5. tryAcquire主要作用尝试加锁。返回 true 加锁成功,返回 false 加锁失败。
    1. 首先getState()判断是否为 0 。(有两种可能为0,一种是锁长时间为自由状态,一种是锁刚刚被释放 短暂的自由状态)
    2. 如果为 0 ,判断 是否有 headNode ,再判断是否 有其他的 head 后面是否有其他线程在排队。
      1. 如果没有队列 或者 队列中没有其他线程在排队,直接 CAS 尝试加锁,加锁成功返回 true, 加锁失败 返回 false。
      2. 加锁成功将AQS 中的 获取锁的线程 设置为 当前 node 线程。
    3. 再判断 持有锁的线程是否是当前线程,也就是判断是否是 重入锁。
      1. 如果是重入锁, state + 1,返回 true。
    4. 否则其他情况返回 false 。
  6. 加锁失败首先会执行 addWaiter 方法,主要作用是将当前 线程封装成 node 插入 tail 和 是否需要初始化队列。
    1. 先将当前线程,封装成 node。
    2. 判断 head 是否为 null
    3. 如果不为 null,说明已经存在队列,设置当前节点 pre 为 tail,当前节点设置为 tail。
    4. 如果为 null,说明不存在队列,去初始化队列。
      1. 首先死循环,判断 tail 是否等于 null ,等于 null 通过 CAS 去初始化为 空节点,赋值给 head,同时tail = head。
      2. tail 不为 null,设置 node pre 为 tail,然后通过CAS 设置 node 为 tail,如果将当前节点 设置为 tail 节点成功。然后跳出循环。(一般是第二次循环会进入这里)
    5. 返回 当前 封装的 head。
  7. 然后会执行 acquireQueued(Node node, int arg)将队列中 node 等待唤醒和尝试加锁。
    1. 死循环,判断当前节点 pre 是否是 head, 也就是为了判断当前节点是否为 队列中第二个等待节点。
    2. 如果是 head ,当前 node 线程 CAS 去尝试获取锁。
      1. 获取成功, 将 当前 node 的 pre 设置为 null,和线程设置为 null。 把 head 的 next 设置 null ,相当于把 head 断开连接,方便gc回收。当前节点设置为 头节点。
      2. 获取失败,则进入 下面的步骤。
    3. 如果获取锁失败 或者 pre 不是 head 节点
      1. 首先判断上一个节点的 waitState 是否为 -1,不是 -1 设置为 -1。
      2. 然后再次循环到这里,会将自己 park住。等待被唤醒。
    4. 如果被其他线程唤醒,则先进行 Thread.interrupted(),这里没什么作用,主要是 lockInterruptibly() 会抛异常。
    5. 被唤醒之后,就会再次进入循环 尝试获取锁。
    6. 出现异常,会走 finally 取消线程获取锁。(一般来讲不会走这里)
  8. 当 Thread.interrupted()为 true,则会调用 selfInterrupt(),重置当前线程 interrupt。
    1. // tryAcquire() 尝试获取锁
    2. // acquireQueued() 入队
    3. // selfInterrupt 消除方法中的 interrupt();
    4. public final void acquire(int arg) {
    5. if (!tryAcquire(arg) &&
    6. acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
    7. selfInterrupt();
    8. }
    1. // lock()方法,等待锁和尝试获取锁逻辑
    2. final boolean acquireQueued(final Node node, int arg) {
    3. boolean failed = true;
    4. try {
    5. boolean interrupted = false;
    6. for (;;) {
    7. final Node p = node.predecessor();
    8. if (p == head && tryAcquire(arg)) {
    9. setHead(node);
    10. p.next = null; // help GC
    11. failed = false;
    12. return interrupted;
    13. }
    14. if (shouldParkAfterFailedAcquire(p, node) &&
    15. parkAndCheckInterrupt())
    16. interrupted = true;
    17. }
    18. } finally {
    19. if (failed)
    20. cancelAcquire(node);
    21. }
    22. }
    1. /*
    2. * Acquires in exclusive interruptible mode.
    3. * @param arg the acquire argument
    4. */
    5. // lockInterruptibly()方法,等待锁和尝试获取锁逻辑
    6. private void doAcquireInterruptibly(int arg)
    7. throws InterruptedException {
    8. final Node node = addWaiter(Node.EXCLUSIVE);
    9. boolean failed = true;
    10. try {
    11. for (;;) {
    12. final Node p = node.predecessor();
    13. if (p == head && tryAcquire(arg)) {
    14. setHead(node);
    15. p.next = null; // help GC
    16. failed = false;
    17. return;
    18. }
    19. if (shouldParkAfterFailedAcquire(p, node) &&
    20. parkAndCheckInterrupt())
    21. throw new InterruptedException();
    22. }
    23. } finally {
    24. if (failed)
    25. cancelAcquire(node);
    26. }
    27. }
    这里的interrupted()或判断是否中断,中断返回true
    lock()的parkAndCheckInterrupt(),返回的是true,那么acquireQueue就返回true
    ,那么就走selfInterrupt(),那么selfInterrupt()那个中断重置了。
    但是在lockInterruptibly(),parkAndCheckInterrupt()会抛弃异常,我们写的方法中就可以捕获该异常。
    结合两者看 selfInterrupt()就有意义了。 ```java // Convenience method to park and then check if interrupted. // @return {@code true} if interrupted

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

```java
// 尝试获取锁的逻辑
protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}
 /**
  * Convenience method to interrupt current thread.
  */
// 方便的方法来中断当前线程,重置。
static void selfInterrupt() {
    Thread.currentThread().interrupt();
}