JDK 8 Condition 源码详解(详细注释版)
1. 类定义和基本属性
public class ConditionObject implements Condition, java.io.Serializable {
// 序列化版本号
private static final long serialVersionUID = 1173984872572414699L;
/**
* 条件等待队列的第一个节点
* 构成一个FIFO的单向链表队列
*/
private transient Node firstWaiter;
/**
* 条件等待队列的最后一个节点
*/
private transient Node lastWaiter;
/**
* Node类继承自AbstractQueuedSynchronizer.Node
* 用于构建条件等待队列
* 在条件队列中,Node的nextWaiter字段指向下一个等待节点
*/
public class Node {
// 节点状态常量
static final int CANCELLED = 1; // 节点已取消
static final int SIGNAL = -1; // 节点需要被唤醒
static final int CONDITION = -2; // 节点在条件队列中等待
static final int PROPAGATE = -3; // 传播(共享模式下使用)
volatile int waitStatus; // 节点状态
volatile Node prev; // 前驱节点(同步队列中使用)
volatile Node next; // 后继节点(同步队列中使用)
volatile Thread thread; // 节点关联的线程
Node nextWaiter; // 指向条件队列中的下一个节点
// 构造方法
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node() {} // 用于建立头节点和哨兵节点
}
/**
* ConditionObject的构造方法
* 通常由AbstractQueuedSynchronizer的newCondition()方法创建
*/
public ConditionObject() { }
2. 核心等待方法(详细注释)
/**
* 使当前线程在条件上等待
* 当前线程必须持有与Condition关联的锁
*
* 等待过程:
* 1. 释放锁(通过AQS的release方法)
* 2. 将当前线程加入条件等待队列
* 3. 阻塞当前线程
* 4. 被唤醒后重新获取锁
*
* 注意事项:
* - 必须在获取锁的情况下调用
* - 会释放锁并在被唤醒后重新获取锁
* - 不响应中断,如果线程被中断会记录中断状态
*
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final void awaitUninterruptibly() {
// 将当前线程加入条件等待队列
Node node = addConditionWaiter();
// 完全释放锁(可重入锁会释放所有重入次数)
int savedState = fullyRelease(node);
boolean interrupted = false;
// 循环等待直到被转移到同步队列
while (!isOnSyncQueue(node)) {
// 阻塞当前线程
LockSupport.park(this);
// 检查是否被中断
if (Thread.interrupted())
interrupted = true;
}
// 重新获取锁并清理中断状态
if (acquireQueued(node, savedState) || interrupted)
selfInterrupt();
}
/**
* 使当前线程在条件上等待
* 这是Condition接口的核心方法
*
* 等待过程:
* 1. 释放锁
* 2. 加入条件等待队列
* 3. 阻塞线程
* 4. 被唤醒后重新获取锁
*
* 中断处理:
* - 如果线程在等待过程中被中断,会抛出InterruptedException
* - 线程可以被优雅地中止
*
* @throws InterruptedException 如果线程被中断
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final void await() throws InterruptedException {
// 检查线程是否被中断
if (Thread.interrupted())
throw new InterruptedException();
// 将当前线程加入条件等待队列
Node node = addConditionWaiter();
// 完全释放锁
int savedState = fullyRelease(node);
int interruptMode = 0;
// 循环等待直到被转移到同步队列
while (!isOnSyncQueue(node)) {
// 阻塞当前线程
LockSupport.park(this);
// 检查中断模式
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 重新获取锁并处理中断
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
/**
* 使当前线程在条件上等待指定时间
*
* 等待过程:
* 1. 释放锁
* 2. 加入条件等待队列
* 3. 阻塞线程或超时返回
* 4. 被唤醒或超时后重新获取锁
*
* 超时处理:
* - 在指定时间内未被唤醒,返回false
* - 被提前唤醒,返回true
* - 等待过程中可被中断
*
* @param time 等待时间
* @param unit 时间单位
* @return 如果被唤醒返回true,如果超时返回false
* @throws InterruptedException 如果线程被中断
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
timedout = transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
/**
* 使当前线程在条件上等待到指定时间点
*
* 等待过程:
* 1. 释放锁
* 2. 加入条件等待队列
* 3. 阻塞线程或到达指定时间
* 4. 被唤醒或超时后重新获取锁
*
* 时间点处理:
* - 在指定时间点前被唤醒,返回false
* - 到达指定时间点仍未被唤醒,返回true
* - 等待过程中可被中断
*
* @param deadline 绝对时间点(纳秒)
* @return 如果超时返回true,如果被提前唤醒返回false
* @throws InterruptedException 如果线程被中断
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (System.currentTimeMillis() > abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
LockSupport.parkUntil(this, abstime);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return timedout;
}
/**
* 使当前线程在条件上等待指定纳秒数
*
* @param nanosTimeout 等待纳秒数
* @return 如果被唤醒返回剩余纳秒数,如果超时返回小于等于0的值
* @throws InterruptedException 如果线程被中断
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return nanosTimeout;
}
3. 核心唤醒方法(详细注释)
/**
* 唤醒一个等待在条件上的线程
*
* 唤醒过程:
* 1. 从条件等待队列中移除第一个节点
* 2. 将该节点转移到同步队列
* 3. 该线程将在下次调度时尝试获取锁
*
* 注意事项:
* - 唤醒的线程不会立即恢复执行
* - 唤醒的线程需要重新竞争锁
* - 必须在持有锁的情况下调用
*
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final void signal() {
// 检查当前线程是否持有锁
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first); // 唤醒第一个等待者
}
/**
* 唤醒所有等待在条件上的线程
*
* 唤醒过程:
* 1. 从条件等待队列中移除所有节点
* 2. 将所有节点转移到同步队列
* 3. 所有线程将在下次调度时尝试获取锁
*
* 使用场景:
* - 条件发生根本性变化
* - 需要唤醒所有等待线程
* - 批量操作完成后的通知
*
* @throws IllegalMonitorStateException 如果没有持有锁
*/
public final void signalAll() {
// 检查当前线程是否持有锁
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first); // 唤醒所有等待者
}
/**
* 实际的单个唤醒操作
* @param first 第一个等待节点
*/
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
/**
* 实际的全部唤醒操作
* @param first 第一个等待节点
*/
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}
/**
* 将节点从条件队列转移到同步队列
* @param node 要转移的节点
* @return 如果转移成功返回true,否则返回false
*/
final boolean transferForSignal(Node node) {
// 如果节点已被取消,转移失败
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 将节点加入同步队列
Node p = enq(node);
int ws = p.waitStatus;
// 如果前驱节点状态不正确,直接唤醒节点
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
4. 辅助方法(详细注释)
/**
* 将当前线程加入条件等待队列
* @return 新创建的节点
*/
private Node addConditionWaiter() {
Node t = lastWaiter;
// 如果尾节点状态不正确,清理取消的节点
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
// 创建新节点并加入队列
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
/**
* 完全释放锁
* 对于可重入锁,会释放所有重入次数
* @param node 节点
* @return 释放前的锁状态
*/
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
/**
* 检查节点是否在同步队列中
* @param node 节点
* @return 如果在同步队列中返回true,否则返回false
*/
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
// 从尾部向前查找
return findNodeFromTail(node);
}
/**
* 从尾部开始查找节点
* @param node 要查找的节点
* @return 如果找到返回true,否则返回false
*/
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
/**
* 清理取消的等待者
* 移除条件队列中状态不正确的节点
*/
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
/**
* 检查等待期间的中断
* @param node 节点
* @return 中断模式
*/
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}
/**
* 处理取消等待后的转移
* @param node 节点
* @return 如果转移成功返回true,否则返回false
*/
final boolean transferAfterCancelledWait(Node node) {
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
// 等待转移完成
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
/**
* 等待后报告中断
* @param interruptMode 中断模式
* @throws InterruptedException 如果是抛出异常模式
*/
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
// 中断模式常量
private static final int REINTERRUPT = 1; // 重新中断
private static final int THROW_IE = 2; // 抛出中断异常
private static final long spinForTimeoutThreshold = 1000L; // 自旋超时阈值
5. 查询方法(详细注释)
/**
* 查询是否有线程在等待此条件
*
* 查询结果:
* - true:有线程在条件等待队列中
* - false:没有线程在等待
*
* 注意事项:
* - 这是一个瞬时状态查询
* - 返回值可能很快过时
* - 主要用于监控和调试
*
* @return 如果有等待线程返回true,否则返回false
*/
public final boolean hasWaiters() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
return true;
}
return false;
}
/**
* 获取等待此条件的线程数量
*
* 查询结果:
* - 返回条件等待队列中的线程数量
* - 这是一个估算值,因为线程状态可能随时变化
*
* 使用场景:
* - 监控条件的使用情况
* - 实现负载监控
* - 性能调优
*
* @return 等待线程数量
*/
public final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
++n;
}
return n;
}
/**
* 获取等待此条件的线程集合
*
* 查询结果:
* - 返回条件等待队列中线程的集合
* - 集合是线程安全的快照
* - 不包含已取消的线程
*
* 使用场景:
* - 调试和诊断
* - 实现管理工具
* - 分析系统状态
*
* @return 等待线程集合
*/
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
6. Condition 的特点分析
核心设计理念:
/**
* Condition的核心设计思想:
*
* 1. 与Lock的绑定关系:
* - Condition必须与特定的Lock实例绑定
* - 每个Lock可以创建多个Condition
* - 提供比内置监视器更灵活的线程等待/通知机制
*
* 2. 条件队列机制:
* - 每个Condition维护独立的等待队列
* - 支持精确的通知控制(signal vs signalAll)
* - 与AQS的同步队列分离
*
* 3. 灵活的等待方式:
* - 支持无限期等待(await)
* - 支持可中断等待(await)
* - 支持超时等待(awaitNanos, awaitUntil)
* - 支持不中断等待(awaitUninterruptibly)
*
* 4. 高效的通知机制:
* - signal()唤醒单个线程
* - signalAll()唤醒所有线程
* - 精确控制唤醒范围
* - 避免不必要的线程唤醒
*
* 5. 状态管理:
* - 自动管理线程的阻塞和唤醒
* - 维护等待队列的一致性
* - 处理中断和超时情况
*
* 6. 与内置监视器的对比:
* - 一个对象一个监视器 vs 一个Lock多个Condition
* - notify/notifyAll vs signal/signalAll
* - synchronized块 vs Lock/Condition组合
* - 更灵活的使用方式
*
* 适用场景:
* - 需要多个等待条件的场景
* - 需要精确控制线程唤醒的场景
* - 需要比内置监视器更灵活的同步机制
* - 实现生产者-消费者模式
* - 实现复杂的线程协调逻辑
*/
性能特征分析:
/**
* Condition的性能特征:
*
* 等待时间复杂度:
* - await():O(1) 加入队列,O(1) 阻塞
* - signal():O(1) 移除队列,O(1) 转移到同步队列
* - signalAll():O(n) 移除所有队列节点
*
* 内存复杂度:
* - O(1) 基本状态开销
* - O(n) 等待队列开销(n为等待线程数)
* - O(1) 每个Condition实例开销
*
* 并发特性:
* - 完全线程安全
* - 与Lock的互操作性保证
* - 支持高并发环境
* - 无锁设计(通过AQS)
*
* 与内置监视器对比:
* - 灵活性:Condition > synchronized
* - 性能:Condition ≥ synchronized(JDK 1.6后)
* - 功能:Condition > synchronized
* - 易用性:synchronized > Condition
*
* 内存使用:
* - 每个等待线程占用一个Node对象
* - 及时GC,避免内存泄漏
* - 条件队列节点在唤醒后被清理
*
* 适用性:
* - 复杂同步逻辑:Condition更优
* - 简单同步需求:synchronized更优
* - 多条件等待:Condition必需
* - 精确唤醒控制:Condition更优
*/
7. 使用示例和最佳实践
/**
* 使用示例:
*
* // 基本使用(生产者-消费者模式)
* class BoundedBuffer {
* final Lock lock = new ReentrantLock();
* final Condition notFull = lock.newCondition(); // 缓冲区不满条件
* final Condition notEmpty = lock.newCondition(); // 缓冲区不空条件
*
* final Object[] items = new Object[100];
* int putptr, takeptr, count;
*
* // 生产者方法
* public void put(Object x) throws InterruptedException {
* lock.lock();
* try {
* // 等待缓冲区不满
* while (count == items.length)
* notFull.await(); // 等待空间
*
* items[putptr] = x;
* if (++putptr == items.length) putptr = 0;
* ++count;
*
* notEmpty.signal(); // 通知消费者有数据
* } finally {
* lock.unlock();
* }
* }
*
* // 消费者方法
* public Object take() throws InterruptedException {
* lock.lock();
* try {
* // 等待缓冲区不空
* while (count == 0)
* notEmpty.await(); // 等待数据
*
* Object x = items[takeptr];
* if (++takeptr == items.length) takeptr = 0;
* --count;
*
* notFull.signal(); // 通知生产者有空间
* return x;
* } finally {
* lock.unlock();
* }
* }
* }
*
* // 多条件等待示例
* class ConditionExample {
* private final Lock lock = new ReentrantLock();
* private final Condition conditionA = lock.newCondition();
* private final Condition conditionB = lock.newCondition();
* private final Condition conditionC = lock.newCondition();
*
* private boolean flagA = false;
* private boolean flagB = false;
* private boolean flagC = false;
*
* // 等待条件A满足
* public void waitForConditionA() throws InterruptedException {
* lock.lock();
* try {
* while (!flagA) {
* conditionA.await();
* }
* // 条件A满足后的处理
* System.out.println("Condition A is satisfied");
* } finally {
* lock.unlock();
* }
* }
*
* // 等待条件B满足
* public void waitForConditionB() throws InterruptedException {
* lock.lock();
* try {
* while (!flagB) {
* conditionB.await();
* }
* // 条件B满足后的处理
* System.out.println("Condition B is satisfied");
* } finally {
* lock.unlock();
* }
* }
*
* // 设置条件A并通知等待者
* public void setConditionA() {
* lock.lock();
* try {
* flagA = true;
* conditionA.signalAll(); // 唤醒所有等待条件A的线程
* } finally {
* lock.unlock();
* }
* }
*
* // 设置条件B并通知等待者
* public void setConditionB() {
* lock.lock();
* try {
* flagB = true;
* conditionB.signal(); // 只唤醒一个等待条件B的线程
* } finally {
* lock.unlock();
* }
* }
* }
*
* // 超时等待示例
* class TimeoutExample {
* private final Lock lock = new ReentrantLock();
* private final Condition condition = lock.newCondition();
* private boolean ready = false;
*
* // 带超时的等待
* public boolean waitForReady(long timeout, TimeUnit unit)
* throws InterruptedException {
* lock.lock();
* try {
* long nanos = unit.toNanos(timeout);
* while (!ready && nanos > 0) {
* nanos = condition.awaitNanos(nanos);
* }
* return ready;
* } finally {
* lock.unlock();
* }
* }
*
* // 带绝对时间的等待
* public boolean waitForReadyUntil(Date deadline)
* throws InterruptedException {
* lock.lock();
* try {
* while (!ready) {
* if (condition.awaitUntil(deadline)) {
* // 被唤醒
* if (!ready) continue;
* else break;
* } else {
* // 超时
* return false;
* }
* }
* return true;
* } finally {
* lock.unlock();
* }
* }
*
* // 设置准备状态并通知
* public void setReady() {
* lock.lock();
* try {
* ready = true;
* condition.signalAll();
* } finally {
* lock.unlock();
* }
* }
* }
*
* // 不可中断等待示例
* class UninterruptibleExample {
* private final Lock lock = new ReentrantLock();
* private final Condition condition = lock.newCondition();
* private boolean ready = false;
*
* // 不可中断的等待
* public void waitForReadyUninterruptibly() {
* lock.lock();
* try {
* while (!ready) {
* condition.awaitUninterruptibly();
* }
* // 处理准备好的情况
* } finally {
* lock.unlock();
* }
* }
*
* // 设置准备状态并通知
* public void setReady() {
* lock.lock();
* try {
* ready = true;
* condition.signalAll();
* } finally {
* lock.unlock();
* }
* }
* }
*
* 最佳实践:
*
* 1. 正确的锁获取和释放:
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* // 等待条件
* lock.lock();
* try {
* while (!conditionMet()) { // 必须使用while循环
* condition.await();
* }
* // 条件满足后的处理
* } finally {
* lock.unlock(); // 必须在finally块中释放锁
* }
*
* // 通知等待者
* lock.lock();
* try {
* setConditionMet(true);
* condition.signal(); // 或者 condition.signalAll();
* } finally {
* lock.unlock();
* }
*
* 2. 使用while循环检查条件:
* // 错误的做法:使用if语句
* lock.lock();
* try {
* if (!conditionMet()) { // 危险!虚假唤醒可能导致问题
* condition.await();
* }
* // 处理逻辑
* } finally {
* lock.unlock();
* }
*
* // 正确的做法:使用while循环
* lock.lock();
* try {
* while (!conditionMet()) { // 正确处理虚假唤醒
* condition.await();
* }
* // 处理逻辑
* } finally {
* lock.unlock();
* }
*
* 3. 选择合适的唤醒方法:
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* // 当只有一个线程需要被唤醒时使用signal()
* public void singleNotification() {
* lock.lock();
* try {
* // 状态改变
* updateState();
* condition.signal(); // 唤醒一个等待者
* } finally {
* lock.unlock();
* }
* }
*
* // 当所有线程都需要被唤醒时使用signalAll()
* public void broadcastNotification() {
* lock.lock();
* try {
* // 状态发生根本性改变
* updateState();
* condition.signalAll(); // 唤醒所有等待者
* } finally {
* lock.unlock();
* }
* }
*
* 4. 处理中断异常:
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* public void interruptibleWait() throws InterruptedException {
* lock.lock();
* try {
* while (!conditionMet()) {
* condition.await(); // 可能抛出InterruptedException
* }
* // 处理逻辑
* } finally {
* lock.unlock();
* }
* }
*
* // 调用方处理中断
* try {
* interruptibleWait();
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt(); // 恢复中断状态
* // 处理中断情况
* }
*
* 5. 设置合理的超时时间:
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* public boolean waitForCondition(long timeout, TimeUnit unit)
* throws InterruptedException {
* lock.lock();
* try {
* long nanos = unit.toNanos(timeout);
* while (!conditionMet() && nanos > 0) {
* nanos = condition.awaitNanos(nanos);
* }
* return conditionMet();
* } finally {
* lock.unlock();
* }
* }
*
* // 使用示例
* try {
* if (waitForCondition(5, TimeUnit.SECONDS)) {
* System.out.println("Condition satisfied within timeout");
* } else {
* System.out.println("Timeout occurred");
* }
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
*
* 6. 使用不可中断等待:
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* public void uninterruptibleWait() {
* lock.lock();
* try {
* while (!conditionMet()) {
* condition.awaitUninterruptibly(); // 不会抛出中断异常
* }
* // 处理逻辑
* } finally {
* lock.unlock();
* }
* }
*
* 7. 监控Condition的使用情况:
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* // 检查是否有线程在等待
* if (condition.hasWaiters()) {
* System.out.println("There are threads waiting on this condition");
* System.out.println("Number of waiting threads: " +
* condition.getWaitQueueLength());
* }
*
* // 获取等待线程列表
* Collection<Thread> waitingThreads = condition.getWaitingThreads();
* for (Thread thread : waitingThreads) {
* System.out.println("Waiting thread: " + thread.getName());
* }
*
* 8. 多条件管理:
* class MultiConditionExample {
* private final Lock lock = new ReentrantLock();
* private final Condition readCondition = lock.newCondition();
* private final Condition writeCondition = lock.newCondition();
* private final Condition errorCondition = lock.newCondition();
*
* private volatile boolean readable = false;
* private volatile boolean writable = false;
* private volatile boolean errorOccurred = false;
*
* public void waitForRead() throws InterruptedException {
* lock.lock();
* try {
* while (!readable && !errorOccurred) {
* readCondition.await();
* }
* if (errorOccurred) {
* throw new RuntimeException("Error occurred while waiting");
* }
* } finally {
* lock.unlock();
* }
* }
*
* public void waitForWrite() throws InterruptedException {
* lock.lock();
* try {
* while (!writable && !errorOccurred) {
* writeCondition.await();
* }
* if (errorOccurred) {
* throw new RuntimeException("Error occurred while waiting");
* }
* } finally {
* lock.unlock();
* }
* }
*
* public void signalReadReady() {
* lock.lock();
* try {
* readable = true;
* readCondition.signalAll();
* } finally {
* lock.unlock();
* }
* }
*
* public void signalWriteReady() {
* lock.lock();
* try {
* writable = true;
* writeCondition.signalAll();
* } finally {
* lock.unlock();
* }
* }
*
* public void signalError() {
* lock.lock();
* try {
* errorOccurred = true;
* readCondition.signalAll();
* writeCondition.signalAll();
* errorCondition.signalAll();
* } finally {
* lock.unlock();
* }
* }
* }
*
* 9. 避免死锁:
* // 确保锁的获取顺序一致
* Lock lock1 = new ReentrantLock();
* Lock lock2 = new ReentrantLock();
* Condition condition1 = lock1.newCondition();
* Condition condition2 = lock2.newCondition();
*
* // 正确的做法:保持一致的锁获取顺序
* public void method1() {
* lock1.lock();
* try {
* lock2.lock();
* try {
* // 业务逻辑
* } finally {
* lock2.unlock();
* }
* } finally {
* lock1.unlock();
* }
* }
*
* public void method2() {
* lock1.lock(); // 保持相同的获取顺序
* try {
* lock2.lock();
* try {
* // 业务逻辑
* } finally {
* lock2.unlock();
* }
* } finally {
* lock1.unlock();
* }
* }
*
* 10. 性能调优:
* // 在高并发场景下监控性能
* Lock lock = new ReentrantLock();
* Condition condition = lock.newCondition();
*
* // 定期检查Condition的使用情况
* if (condition.getWaitQueueLength() > 100) {
* System.out.println("High contention detected on condition");
* // 可能需要优化同步逻辑
* }
*
* // 使用条件变量减少不必要的唤醒
* public void optimizedNotification() {
* lock.lock();
* try {
* // 只在必要时发送通知
* if (needToNotify()) {
* updateState();
* condition.signal(); // 精确通知
* }
* } finally {
* lock.unlock();
* }
* }
*/
8. 与其他同步机制的比较
/**
* Condition vs Object's wait/notify vs CountDownLatch vs Semaphore:
*
* Condition:
* - 与特定Lock绑定
* - 支持多个等待条件
* - 精确的唤醒控制
* - 支持超时和中断
* - 灵活的使用方式
*
* Object's wait/notify:
* - 与对象监视器绑定
* - 一个对象一个等待队列
* - notify/notifyAll唤醒
* - synchronized关键字使用
* - 功能相对简单
*
* CountDownLatch:
* - 一次性同步工具
* - 倒计数机制
* - 不支持重置
* - 适用于等待多个事件完成
*
* Semaphore:
* - 计数信号量
* - 控制资源访问数量
* - 支持公平性和非公平性
* - 适用于资源池管理
*
* 选择建议:
* - 复杂同步逻辑:Condition
* - 简单等待/通知:Object's wait/notify
* - 等待事件完成:CountDownLatch
* - 资源访问控制:Semaphore
* - 生产者-消费者:Condition或BlockingQueue
*
* 性能对比:
* - 简单场景:Object's wait/notify ≈ Condition
* - 复杂场景:Condition > Object's wait/notify
* - 一次性同步:CountDownLatch最优
* - 资源控制:Semaphore最优
*
* 功能对比:
* - 多条件支持:Condition独有
* - 精确唤醒:Condition > Object's wait/notify
* - 超时控制:Condition ≥ Object's wait/notify
* - 中断支持:Condition ≥ Object's wait/notify
* - 易用性:Object's wait/notify > Condition
*/
9. 总结
Condition 的核心特性:
-
与Lock的绑定关系:
- 必须与特定的Lock实例绑定
- 每个Lock可以创建多个Condition
- 提供比内置监视器更灵活的机制
-
条件队列机制:
- 每个Condition维护独立的等待队列
- 支持精确的通知控制
- 与AQS的同步队列分离
-
灵活的等待方式:
- 支持无限期、可中断、超时、不可中断等待
- 提供多种等待方法满足不同需求
- 自动处理线程阻塞和唤醒
-
高效的唤醒机制:
- signal()精确唤醒单个线程
- signalAll()唤醒所有等待线程
- 避免不必要的线程唤醒
-
丰富的查询API:
- 提供详细的等待状态信息
- 支持监控和诊断
- 便于调试和性能调优
-
线程安全:
- 所有操作都是线程安全的
- 与Lock的互操作性保证
- 支持高并发环境
适用场景:
- 需要多个等待条件的复杂同步场景
- 需要精确控制线程唤醒的场景
- 生产者-消费者模式的实现
- 实现复杂的线程协调逻辑
- 需要比内置监视器更灵活的同步机制
注意事项:
- 必须在获取锁的情况下调用await/signal方法
- 等待条件时必须使用while循环检查
- 正确处理中断异常
- 合理选择signal和signalAll方法
- 在finally块中释放锁
- 避免死锁和竞态条件
性能优化建议:
- 根据业务需求选择合适的等待方式
- 合理使用超时控制避免无限等待
- 选择合适的唤醒方法减少不必要唤醒
- 监控Condition的使用情况
- 优化条件检查逻辑减少虚假唤醒
- 保持一致的锁获取顺序避免死锁
- 定期分析和调优同步逻辑
- 使用条件变量减少不必要的通知