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
,我们可以实现更灵活的线程同步