AQS 和 ReentrantLock的一些详尽分析

AbstractQueuedSynchronizer是实现同步的基础组件,简称AQS,JUC的锁底层就是AQS实现的。ReentrantLock是AQS的一个实现。先看类图结构:

ReentrantLock

ReentrantLock实现了Lock接口

1.成员变量
在这里插入图片描述
很简单,一个Sync类的snyc
2.方法
在这里插入图片描述
3.内部类
在这里插入图片描述

Sync(成员变量不讨论)

Sync继承了AbstractQueuedSynchronizer抽象类

1.方法:
在这里插入图片描述

NonfairSync(成员变量不讨论)

1.方法:
在这里插入图片描述

FairSync(成员变量不讨论)

1.方法:
在这里插入图片描述


AbstractQueuedSynchronizer

1.成员变量
在这里插入图片描述
2.内部类
在这里插入图片描述

Node

1.成员变量
在这里插入图片描述

ConditionObject:以后讨论


正片开始

一、看源码前知识

part.1 AbstractQueuedSynchronizer
AQS组件介绍:
  • AQS是一个FIFO的双向队列,其中head和tail节点来维护链表队列。它们初始状态是head = tail = null。

  • 队列的元素是AQS的内部类Node。

    • Node有next和prev指针来维护双向队列。
    • Node有一个waitStatus来记录本节点的阻塞状态
  • AQS有一个非常重要的成员变量state。它是实现锁的核心,在不同实现的锁中代表不同的意义。但是锁都通过原子性地改变state的值,实现同步。state相对于一个标记。

    • 对于ReentrantLock:state是获得锁线程可重入次数
    • 对于ReentrantReadWriteLock:state高16位表示读锁获取次数,低16位表示写锁的可重入次数。
    • 对于Semaphore:state表示信号量个数
    • 对于CountDownLatch:state表示计数器当前值
  • acquire()方法:调用实现类的tryAcquire()方法来试图获取锁,tryAcquire()有两个结果:

    1. 获取锁(或重入锁)成功,设置当前线程为持有锁线程,返回true。
    2. 获取锁失败,返回false。
    • 如果tryAcquire()返回false,那么acquire()会调用addWaiter()方法和acquireQueued()方法来把未获得锁的该线程装进一个new出来的Node中,并把该Node放入AQS阻塞队列,并且acquireQueued()会调用parkAndCheckInterrupt()方法通过 LockSpport类来park()该线程,让该线程阻塞。(该过程还存在2次自旋、AQS阻塞队列是否初始化的问题)
  • tryAcquire()方法:上面已经叙述。⚠️tryAcquire()由AQS的子类实现。作用是通过改变state的值获取锁。并且返回获取锁成功还是失败的boolean值。返回给acquire()方法。

  • addWaiter()方法:为阻塞线程new出Node并且入队。

  • acquireQueued()方法:在AQS队列已存在的情况下,该方法直接把新的Node装载的线程park()掉。对创世线程,该方法会两次自旋再次检查锁能否被该线程获取,不能的话最后也会将装载该线程的Node放入刚刚初始化的AQS阻塞队列(该过程会初始化AQS阻塞队列)。

  • release()方法:

  • tryRelease()方法:

  • parkAndCheckInterrupt()方法

AQS思想介绍:
  • AQS核心就是通过LockSpport的park方法来阻塞队列。
  • 线程通过少量的自旋来检查并尝试获取锁。
  • AQS通过head、tail以及Node类来维护链表队列。
  • 线程间同步(加锁)通过原子性地修改state实现。
AQS结合ReentrantLock的流程介绍:
  1. 当多个线程调用ReentrantLock的lock.lock()时,只有一个线程t1获取到了锁。第二个线程t2会初始化AQS队列并且转换为Node节点入队阻塞队列(线程t2还会进行两次自旋操作来检查锁是否在初始化AQS队列的过程中被释放来,被释放了的化就立刻获取锁),其他线程也会转换为Node节点入队阻塞队列。
  2. 如果获取到锁的t1线程在执行临界区时,发现自己不满足条件,于是调用条件变量conditionObject的await()方法。那么t1会释放锁,并且被转换为Node节点进入该条件变量维护的条件队列中。
  3. 这时候,AQS队列中的线程也会被唤醒并且自旋尝试获取锁。如果获取了锁但是也调用了条件变量conditionObject的await()方法,那么也将被转换为Node节点进入该条件变量维护的条件队列中。
  4. 当另外一个线程调用了conditionObject的signalAll()方法时,会把条件队列里的一个或全部Node移动到AQS队列中,等待获取锁。
    在这里插入图片描述

二、看源码(以公平锁为例)

第一个线程
  1. Test.java (测试类)
    假设第一个线程执行了如下代码:
ReentrantLock lock2 = new ReentrantLock(true);
lock.lock(); < — — — — — a.进去
  1. ReentrantLock
public void lock() {
       sync.lock();   < — — — — — b.进去
  1. ReentrantLock.Sync
abstract void lock();  < — — — — — c.进实现类去
  1. ReentrantLock.FairSync
final void lock() {
      acquire(1);   < — — — — — d.进夫父类去
      }
  1. AbstractQueuedSynchronizer
    先执行tryAcquire(arg),其中arg = 1
// 1.该方法先执行tryAcquire(arg),返回true就走了。返沪false则执行&&右边
// 	tryAcquire(arg)是为了加锁(设state)
// 2.执行addWaiter(Node.EXCLUSIVE):生成node(初始化队列)并入队
// 3.执行acquireQueued()去再次自旋获取锁,失败就park阻塞线程
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&  < — — — — — e.进夫实现类去
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
    }
  1. ReentrantLock.FairSync
// 该方法主要通过CAS设置state来获得锁
// 该方法是公平锁策略,拿锁前要判断是否排队
// 或者增加重入数量
protected final boolean tryAcquire(int acquires) {
      // 获得该线程实例
      final Thread current = Thread.currentThread();
      // 获得此时的state值,默认 state = 0
      int c = getState();
      // c == 0,进入下面if语句
      if (c == 0) {
          // 判断是否需要排队,返回false,执行第二句compareAndSetState(0, acquires))
          // cas成功,进入if
          // 执行setExclusiveOwnerThread(current):把当前线程设为持有锁线程
          if (!hasQueuedPredecessors() &&
              // 设置state = 1
              compareAndSetState(0, acquires)) {
              setExclusiveOwnerThread(current);
              return true;     < — — — — — f.返回e: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;
        }
  1. 最终返回
ReentrantLock lock2 = new ReentrantLock(true);
lock.lock(); 	< — — — — — g.返回结束,获取了锁
第二个线程
  1. Test.java (测试类)
    现在第一个线程已经获得了锁,且持有锁没放。第二个线程现在过来试图获取锁
ReentrantLock lock2 = new ReentrantLock(true);
lock.lock(); < — — — — — a.进去
  1. ReentrantLock
public void lock() {
       sync.lock();   < — — — — — b.进去
  1. ReentrantLock.Sync
abstract void lock();  < — — — — — c.进实现类去
  1. ReentrantLock.FairSync
final void lock() {
      acquire(1);   < — — — — — d.进夫父类去
      }
  1. AbstractQueuedSynchronizer
    先执行tryAcquire(arg),其中arg = 1
// 1.该方法先执行tryAcquire(arg),返回true就走了。返沪false则执行&&右边
// 	tryAcquire(arg)是为了加锁(设state)
// 2.执行addWaiter(Node.EXCLUSIVE):生成node(初始化队列)并入队
// 3.执行acquireQueued()去再次自旋获取锁,失败就park阻塞线程
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&  < — — — — — e.进夫实现类去
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
    }
  1. ReentrantLock.FairSync
// 该方法主要通过CAS设置state来获得锁
// 该方法是公平锁策略,拿锁前要判断是否排队
// 或者增加重入数量
protected final boolean tryAcquire(int acquires) {
      // 获得该线程实例
      final Thread current = Thread.currentThread();
      // 获得此时的state值,由于有线程1持有锁,所以state = 1
      int c = getState();
      // c == 1,跳过下面if语句
      if (c == 0) {
          if (!hasQueuedPredecessors() &&
              compareAndSetState(0, acquires)) {
              setExclusiveOwnerThread(current);
              return true;     
          }
      }
      // 由于该线程不是持有锁线程,所以跳过else if语句
      else if (current == getExclusiveOwnerThread()) {
          int nextc = c + acquires;
          if (nextc < 0)
              throw new Error("Maximum lock count exceeded");
              setState(nextc);
              return true;           
              }
          return false;     < — — — — — f.最终返回false返回e
        }
  1. AbstractQueuedSynchronizer
public final void acquire(int arg) {
	// tryAcquire(arg)返回false,!tryAcquire(arg) 为true,执行 && 右
    if (!tryAcquire(arg) &&  
        // 调用(addWaiter(Node.EXCLUSIVE)方法
        // 调用acquireQueued()方法
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))   < — — — — — g.进入(addWaiter(Node.EXCLUSIVE)方法
        selfInterrupt();
    }
  1. AbstractQueuedSynchronizer
// 该方法生成一个新的Node,装载该线程
// 调用enq(node)方法入队/初始化阻塞队列
private Node addWaiter(Node mode) {
	    // 新建一个Node,装载当前进程
        Node node = new Node(Thread.currentThread(), mode);
        // Node的pred指向tail,此时tail = head = null
        Node pred = tail;
        // 跳过if语句
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);  < — — — — — h.进入enq(node)方法
        return node;
    }
  1. AbstractQueuedSynchronizer
//该函数初始化了队列,新建了head的Node节点。并且将node入队
private Node enq(final Node node) {
      // 无限循环
      for (;;) {
          // [循环1:t就是tail]
          // [循环2:t就是tail]
          Node t = tail;
          // [循环1:现在tail == t == null,进入if]
          // [循环2:现在t!= null, 跳过if]
          if (t == null) { 
              // [循环1:CAS设置头部head为一个新建的空的Node]
              if (compareAndSetHead(new Node()))
                  // [循环1:tail == head == new Node(),如下图2]
                  tail = head;    // [循环1:图3] 循环1结束
          // [循环2:进入else]
          } else {
              // [循环2:node的prev指向t(tail)]
              node.prev = t;   // [循环2:图4]
              // [循环2: CAS设置尾为node]
              if (compareAndSetTail(t, node)) {
                  // [循环2: 前节点的next指向node]
                  t.next = node;   //[循环2:图4]
                  return t;        < — — — — i.返回h
              }

在这里插入图片描述
图1 在这里插入图片描述
图2 在这里插入图片描述
图3 在这里插入图片描述
图4

  1. AbstractQueuedSynchronizer
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&  
        // 由于acquireQueued()方法阻塞,此处也阻塞等待acquireQueued返回
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))  < — — — — — j.进入acquireQueued()方法
        selfInterrupt();
    }
  1. AbstractQueuedSynchronizer
// 1.该函数是自旋的死循环,打破的地方在唯一的return处
// 2.该函数第2次循环,才把线程park掉。给了它两次循环的机会
// 3.park掉后线程就在park的地方阻塞了,等待unpark唤醒
// 4.第2点,如果是不是队列来的第一个node,那么它前继不是head,那么它不会走第一个if。它会等到它的prev是head的时候,才有机会返回。
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        // 死循环
        for (;;) {
            // [循环1:p是node的前节点,也就是空空的head]
            // [循环2:同上]
            final Node p = node.predecessor();
            // [循环1:p是head, 所以此时执行tryAcquire(arg)。其实就是在去尝试获得一次锁,相对于第一次自旋]
            // [循环1: 因为有可能在初始化队列的过程中, 线程1已经释放锁了]
            // [循环1: 能拿到锁就尽量拿,免得去park。park会调用操作系统资源,很消耗
            // 如果tryAcquire(arg)成功,则进入if,则setHead(node):这里不展开。大概就是把线程2出队,node的thread内容情况,变成一个空的head
            // [循环1:此处tryAcquire(arg)失败,跳过if]
            // ----------------------------------------
            // [循环2:同上, 第二次自旋尝试获得锁,失败,跳过if]
            // ...很久以后的开始循环3
            // [循环3次: 终于tryAcquire(arg)成功,可以获得锁了,进入if
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                // [循环3: 返回true
                return interrupted;     < — — — — — m.返回false
            }
            // [循环1: 执行shouldParkAfterFailedAcquire(p, node)
            // [循环1: 该函数很复杂,大概就是让它不失败,再去自旋一次取锁
            // [循环1: 它会设置head的waitStatus为-1,并且返回false
            // [循环1: 那么跳过if。死循环第二轮开始]
            // ---------------------------------------------
            // [循环2: 执行shouldParkAfterFailedAcquire(p, node)]
            // [循环2: 这次执行就返回true]
            // [循环2: 执行parkAndCheckInterrupt()]
            // [循环2: 会调用LockSupport.park(this)
            // [循环2: 终于park了,线程在次停住。等待parkAndCheckInterrupt()返回
            // ...很久以后
            // [循环2: 很久以后,parkAndCheckInterrupt()终于返回了false,循环2继续,跳过if
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())  < — — — — — k.进入parkAndCheckInterrupt()方法
                interrupted = true;   
        }
    } finally {
        if (failed)
            cancelAcquire(node);
  1. AbstractQueuedSynchronizer
private final boolean parkAndCheckInterrupt() {
        // 1.park阻塞此线程,线程在停住。等待unpark唤醒
        LockSupport.park(this);
        // ...过了很久
        // 2. 线程1释放lock,线程2在此处唤醒,被unpark()唤醒了
        // 返回Thread.interrupted(),返回false
        return Thread.interrupted();    < — — — — — l.返回false
    }
  1. AbstractQueuedSynchronizer
public final void acquire(int arg) {
    // 现在!tryAcquire(arg)为true
    // acquireQueued(addWaiter(Node.EXCLUSIVE)终于返回false
    // 所以整体为false,跳过if体
    if (!tryAcquire(arg) &&  
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 
        selfInterrupt();     
    }       < — — — — n.返回d、c、b、a 结束
  1. AbstractQueuedSynchronizer
static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

以上13步,还有一中可能是被park的线程2被中断唤醒,那么parkAndCheckInterrupt()方法就会返回true。又是另外一番故事了

收工!


释放锁

第一个线程释放锁unlock源码
  1. Test.java (测试类)
    现在第一个线程执行了如下代码,释放锁:
lock.unlock(); < — — — — — a.进去
  1. ReentrantLock
public void unlock() {
        sync.release(1);   < — — — — — b.进去
    }
  1. AbstractQueuedSynchronizer
public final boolean release(int arg) {
	// 此时arg = 1,执行tryRelease(arg)
    if (tryRelease(arg)) {     < — — — — — c.进去tryRelease(arg)
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
    }
  1. ReentrantLock
protected final boolean tryRelease(int releases) {
	  // c = 1 - 0。由于线程1持有锁,并且重入数为1,所以getState()==1
      int c = getState() - releases;
      if (Thread.currentThread() != getExclusiveOwnerThread())
          throw new IllegalMonitorStateException();
      boolean free = false;
      // 进入if
      if (c == 0) {
          free = true;
          setExclusiveOwnerThread(null);
      }
      // 设置state为0
      setState(c);
      // 返回true
      return free;        < — — — — — d.返回false到c
        }
  1. AbstractQueuedSynchronizer
public final boolean release(int arg) {
	// tryRelease(arg)返回true,进入if
    if (tryRelease(arg)) {     
        // h 为那个空空的头
        Node h = head;
        // h不为空,waitStatus == -1,进入if
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);  < — — — — — e.进入unparkSuccessor(h)
        return true;
    }
    return false;
    }
  1. AbstractQueuedSynchronizer
private void unparkSuccessor(Node node) {
        // 传入的h为空空的head,ws = -1
        int ws = node.waitStatus;
        // 进入if
        if (ws < 0)
        	// CAS设置h的waitStatus为0
            compareAndSetWaitStatus(node, ws, 0);

		// 得到线程2的Node,用s指向它
        Node s = node.next;
        // 线程2的Node不为空,且线程2的Node的waitStatus == -1,跳过if
        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;
        }
        // unpark(线程2)
        if (s != null)
            LockSupport.unpark(s.thread);  < — — — — 被阻塞的线程2被唤醒,结束

入队的其他两种情况

假设此时阻塞队列已经初始化:

情况一、队列中元素>1个
假设t1已加锁,t2已进入阻塞队列,t3也已进入阻塞队列排在t2后。此时t1释放了锁,阻塞队列的空空的head被gc清理。t2的node清空thread成员,晋升为阻塞队列的head,此时阻塞队列有t2(head)——>t3。
那么此时,t2被唤醒,自旋调用tryAcquire()方法,还要检查自己是否需要排队。

ReentrantLock

protected final boolean tryAcquire(int acquires) {
	   // current == t2
       final Thread current = Thread.currentThread();
       // c == 0
       int c = getState();
       // 进入if
       if (c == 0) {
           // 检查是否需要排队hasQueuedPredecessors()
           if (!hasQueuedPredecessors() &&   < — — — — — a.进入
               compareAndSetState(0, acquires)) {
               setExclusiveOwnerThread(current);
               return true;
           }
       }

AbstractQueuedSynchronizer

public final boolean hasQueuedPredecessors() {
        Node t = tail; 
        Node h = head;
        Node s;
        // (h != t)为true
        //((s = h.next) == null) 为false
        //(s.thread != Thread.currentThread())s是t3,所以为false
        // 整体返回 false
        return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());     < — — — — — b.返回false
    }

ReentrantLock

protected final boolean tryAcquire(int acquires) {
	   // current == t2
       final Thread current = Thread.currentThread();
       // c == 0
       int c = getState();
       // 进入if
       if (c == 0) {
           // hasQueuedPredecessors()返回false
           // (!hasQueuedPredecessors())整体为true
           // 执行 && 右边CAS,试图获得锁
           if (!hasQueuedPredecessors() &&   
               compareAndSetState(0, acquires)) {
               setExclusiveOwnerThread(current);
               return true;
           }
       }

情况二、队列中元素 = 1个
t1刚刚释放,head被清理。队列只有t2,t2的node晋升为空空的head。此时就只有一个元素。t2唤醒自旋、调用tryAcquire()方法。经过判断,hasQueuedPredecessors()返回 -true- false,因为此时head == tail。
AbstractQueuedSynchronizer

public final boolean hasQueuedPredecessors() {
        Node t = tail; 
        Node h = head;
        Node s;
        // (h != t)为false
        return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());     < — — — — — b.返回false
    }

分析 lock.lockInterruptibly()

可以看到,在源码分析13步:
13. AbstractQueuedSynchronizer

private final boolean parkAndCheckInterrupt() {
        // 1.park阻塞此线程,线程在停住。等待unpark唤醒
        LockSupport.park(this);
        // ...过了很久
        // 2. 线程1释放lock,线程2在此处唤醒,被unpark()唤醒了
        // 返回Thread.interrupted(),返回false
        return Thread.interrupted();    < — — — — — l.返回false
    }

在这里似乎Thread.interrupted()正常情况一定返回false,因为没有打断。就算打断了,返回false,一路返回回去,也没有任何效果,线程会继续尝试获取锁。所以看出这段代码在lock.lock()中没有任何意义。那到底什么意思呢?其实是因为这段代码被lock.lockInterruptibly()复用了,它在lock.lockInterruptibly()里才起了作用。可能是作者偷懒了。来看lock.lockInterruptibly():

  1. Test类
try {
       lock.lockInterruptibly();   < — — — — — a.进入
   } catch (InterruptedException e) {
       System.out.println("lockInterruptibly throws");
  1. ReentrantLock
public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);   < — — — — — b.进入
    }
  1. AbstractQueuedSynchronizer
public final void acquireInterruptibly(int arg)
            throws InterruptedException {
     //先检查本线程有没有打断过,有的话就抛出异常
    if (Thread.interrupted())
        throw new InterruptedException();
    // 尝试获取锁,失败就进入if(此时假设有t1持有,t2失败)
    if (!tryAcquire(arg))
        doAcquireInterruptibly(arg);   < — — — — — c.进入
    }
  1. AbstractQueuedSynchronizer
private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
    final Node node = addWaiter(Node.EXCLUSIVE);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return;
            }
            // 依旧,在自旋2次拿不到锁的时候,进入parkAndCheckInterrupt()去park阻塞
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())   < — — — — — c.进入
                throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
  1. AbstractQueuedSynchronizer
private final boolean parkAndCheckInterrupt() {
		// 再次阻塞,要么等待unpark唤醒,要么等死直到interrupt唤醒
        LockSupport.park(this);
        // 如果interrupt唤醒,返回true
        return Thread.interrupted();   < — — — — — d.返回true
    }
  1. AbstractQueuedSynchronizer
private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
    final Node node = addWaiter(Node.EXCLUSIVE);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return;
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())   
                throw new InterruptedException();  < — — — — — e.抛出异常,结束
        }
    } finally {
        if (failed)
            cancelAcquire(node);

注意⚠️
在源码分析14步,该过程是lock.lock()调用的
14. AbstractQueuedSynchronizer

public final void acquire(int arg) {
    // 现在!tryAcquire(arg)为true
    // acquireQueued(addWaiter(Node.EXCLUSIVE)终于返回false
    // 所以整体为false,跳过if体
    if (!tryAcquire(arg) &&  
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 
        selfInterrupt();     
    }       < — — — — n.返回d、c、b、a 结束

如果lock.lock()阻塞过程中,有人中断了t2线程。也就是

	t2.interrupt();

那么13步,会返回true,Thread.interrupted() == true
13. AbstractQueuedSynchronizer

private final boolean parkAndCheckInterrupt() {
        // 1.park阻塞此线程,线程在停住。等待unpark唤醒
        LockSupport.park(this);
        // ...过了很久
        // 2. 线程1释放lock,线程2在此处唤醒,被unpark()唤醒了
        // 返回Thread.interrupted(),返回false
        return Thread.interrupted();    < — — — — — l.返回false
    }

那么14步会执行if语句体:selfInterrupt()

AbstractQueuedSynchronizer

static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }

这一步是什么意思呢?之前说它毫无意义,是作者偷懒。是的,但是这一步就是一种补救。补救在lock.lock()被中断的情况下,Thread.interrupted()返回了true,但是该方法会清零中断标志,所以下一次调用会返回false,等用户自己想来获取t2的中断标志时就会返回false。这样就不对,所以执行selfInterrupt()再次中断一次,把中断标志归位。这样以后用户想获取t2中断状态时,就能得到true。

发布了17 篇原创文章 · 获赞 18 · 访问量 5559

猜你喜欢

转载自blog.csdn.net/Vincentqqqqqqq/article/details/104948851
今日推荐