返回

从ReentrantLock Condition原理源码分析ReentrantLock下之WaitSet的原理

后端

前言

在ReentrantLock源码分析的上一篇博客中,我们初步分析了ReentrantLock的加锁、解锁机制,在此篇博客中,我们将进一步深入ReentrantLock源码,分析Condition的原理。

Condition的await方法

public final void await() throws InterruptedException {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    await(0L, 0L);
}

从代码中可以看出,await方法首先检查当前线程是否持有独占锁,如果不是,则抛出IllegalMonitorStateException异常。随后,await方法调用了await(0L, 0L)方法,该方法的作用是让当前线程进入等待状态,直到被其他线程唤醒。

Condition的signal方法

public final void signal() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    signalFalse(false);
}

signal方法首先检查当前线程是否持有独占锁,如果不是,则抛出IllegalMonitorStateException异常。随后,signal方法调用了signalFalse(false)方法,该方法的作用是唤醒一个处于等待状态的线程。

Condition的signalAll方法

public final void signalAll() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    signalFalse(true);
}

signalAll方法首先检查当前线程是否持有独占锁,如果不是,则抛出IllegalMonitorStateException异常。随后,signalAll方法调用了signalFalse(true)方法,该方法的作用是唤醒所有处于等待状态的线程。

WaitSet的原理

在分析Condition的源码时,我们会发现一个叫做WaitSet的类,该类是用来管理处于等待状态的线程的。WaitSet是一个队列,它将处于等待状态的线程按照FIFO(先进先出)的顺序存储起来。

当一个线程调用Condition的await方法时,它会被添加到WaitSet队列中。当一个线程调用Condition的signal或signalAll方法时,它会唤醒一个或多个处于等待状态的线程。被唤醒的线程会从WaitSet队列中删除,并继续执行。

Condition唤醒机制

当一个线程调用Condition的await方法时,它会被挂起,并进入等待状态。此时,线程的状态会变成WAITING。当一个线程被唤醒时,它的状态会变成RUNNABLE

线程的状态变化过程如下:

  1. 线程调用Condition的await方法,进入等待状态,线程状态变成WAITING
  2. 其他线程调用Condition的signal或signalAll方法,唤醒一个或多个处于等待状态的线程。
  3. 被唤醒的线程从WaitSet队列中删除,并继续执行,线程状态变成RUNNABLE

结语

通过对ReentrantLock中Condition源码的分析,我们了解了Condition的原理,以及线程被唤醒后的状态变化。这些知识对我们理解ReentrantLock的锁机制和线程同步机制非常有帮助。