AQS不直接提供await/signal,它们属于Condition接口,需通过ReentrantLock等同步组件创建的Condition实例调用;调用前必须先获取锁,否则抛IllegalMonitorStateException。

在 Java 中,AQS(AbstractQueuedSynchronizer)本身不直接提供 await 和 signal 方法,这些方法属于 Condition 接口,而 Condition 的具体实现(如 ConditionObject)是 AQS 的内部类。要调用 await 和 signal,必须通过由 AQS 同步组件(如 ReentrantLock)创建的 Condition 实例来操作。
必须先获取锁才能调用 await
await() 是一个**可中断、释放锁并挂起当前线程**的操作,它要求调用前当前线程已持有与该 Condition 关联的锁。否则会抛出 IllegalMonitorStateException。
- 以
ReentrantLock为例:需先调用lock.lock()获取锁,再调用condition.await() -
await()内部会原子性地释放锁,并将当前线程加入该Condition的等待队列 - 被
signal()唤醒后,线程需重新竞争同步状态(即重新获取锁),成功后才从await()返回
signal 和 signalAll 必须在持有锁时调用
signal() 和 signalAll() 不会释放锁,但同样要求调用线程**已持有对应锁**,否则抛异常。
-
signal()将等待队列中第一个节点(如果存在)转移到 AQS 的同步队列尾部,使其有机会参与锁竞争 -
signalAll()将整个Condition等待队列中的所有节点一次性转移至同步队列 - 唤醒操作只是“通知”,不保证立即执行;被唤醒线程仍需等锁释放后才能真正恢复运行
典型使用模式(带 try-finally 保证解锁)
为避免死锁或资源泄漏,应严格遵循“加锁 → 检查条件 → 等待/操作 → 解锁”结构:
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (!someConditionMet()) {
condition.await(); // 释放锁并等待
}
// 执行满足条件后的业务逻辑
} finally {
lock.unlock(); // 必须确保解锁
}
// 另一线程中触发唤醒:
lock.lock();
try {
// 修改共享状态,使 someConditionMet() 可能为 true
condition.signal(); // 或 signalAll()
} finally {
lock.unlock();
}
注意 Condition 与锁的绑定关系
每个 Condition 实例都绑定到创建它的那个 Lock(即 AQS 同步器)实例上,不能混用:
- 不同
Lock创建的Condition互不兼容 - 同一个
Lock可创建多个Condition,用于表达不同等待条件(如“非空”、“非满”) -
await()只会让线程进入当前Condition的等待队列,signal()也只能唤醒该队列中的线程
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











