从ReentrantLock Condition原理源码分析ReentrantLock下之WaitSet的原理
2023-12-31 19:00:40
前言
在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
。
线程的状态变化过程如下:
- 线程调用Condition的await方法,进入等待状态,线程状态变成
WAITING
。 - 其他线程调用Condition的signal或signalAll方法,唤醒一个或多个处于等待状态的线程。
- 被唤醒的线程从WaitSet队列中删除,并继续执行,线程状态变成
RUNNABLE
。
结语
通过对ReentrantLock中Condition源码的分析,我们了解了Condition的原理,以及线程被唤醒后的状态变化。这些知识对我们理解ReentrantLock的锁机制和线程同步机制非常有帮助。