Condition
约 328 字大约 1 分钟
2024-08-08
使用 ReentrantLock 比直接使用 synchronized 更安全,可以替代 synchronized 进行线程同步,使用 Condition 对象来实现 wait 和 notify 的功能
我们仍然以 TaskQueue 为例,把前面用 synchronized 实现的功能通过 ReentrantLock 和 Condition 来实现
class TaskQueue {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private Queue<String> queue = new LinkedList<>();
public void addTask(String s) {
lock.lock();
try {
queue.add(s);
condition.signalAll();
} finally {
lock.unlock();
}
}
public String getTask() {
lock.lock();
try {
while (queue.isEmpty()) {
condition.await();
}
return queue.remove();
} finally {
lock.unlock();
}
}
}使用 Condition 时,引用的 Condition 对象必须从 Lock 实例的 newCondition() 返回,这样才能获得一个绑定了 Lock 实例的 Condition 实例
Condition 提供的 await()、signal()、signalAll() 原理和 synchronized 锁对象的 wait()、notify()、notifyAll() 是一致的,并且其行为也是一样的
await()会释放当前锁,进入等待状态signal()会唤醒某个等待线程signalAll()会唤醒所有等待线程
唤醒线程从 await() 返回后需要重新获得锁
此外,和 tryLock() 类似,await() 可以在等待指定时间后,如果还没有被其他线程通过 signal() 或 signalAll() 唤醒,可以自己醒来
if (condition.await(1, TimeUnit.SECOND)) {
// 被其他线程唤醒
} else {
// 指定时间内没有被其他线程唤醒
}可见,使用 Condition 配合 Lock,我们可以实现更灵活的线程同步