synchronized 中可以使用 waitnotify 来实现线程在条件不满足时等待,条件满足时被唤醒。
ReentrantLock 中使用 Condition 对象来实现 waitnotify 对应的功能。
这里将 6.wait 和 notify.md 里的 TaskQueue 使用 ReentrantLockCondition 来实现一遍:

  1. class TaskQueue {
  2. private final Lock lock = new ReentrantLock();
  3. private final Condition condition = lock.newCondition();
  4. private Queue<String> queue = new LinkedList<>();
  5. public void addTask(String s) {
  6. lock.lock();
  7. try {
  8. queue.add(s);
  9. condition.signalAll(); // singnalAll -> notifyAll
  10. } finally {
  11. lock.unlock();
  12. }
  13. }
  14. public String getTask() {
  15. lock.lock();
  16. try {
  17. while (queue.isEmpty()) {
  18. condition.await(); // await -> wait
  19. }
  20. return queue.remove();
  21. } finally {
  22. lock.unlock();
  23. }
  24. }
  25. }

使用 Condition 时,引用的 Condition 对象必须从 Lock 实例的 newCondition() 返回,这样才能获得一个绑定了 Lock 实例的 Condition 实例。
Condition 中使用等待和唤醒与 synchronized 的函数差异:

  • await() -> wait() , 会释放当前锁,进入等待状态。
  • single() -> notify() , 会唤醒某个等待线程。
  • singleAll() -> notifyAll(), 会唤醒所有等待线程。

ReentranttryLock() 类似,await() 可以等待指定时间后,如果没有其他线程通过 single()singleAll() 唤醒,它会自己醒来。

  1. if (condition.await(1, TimeUnit.SECOND)) { // 等待时长为 1 秒
  2. // 被其他线程唤醒
  3. } else {
  4. // 指定时间内没有被其他线程唤醒
  5. }

小结

Condition 可以替代 waitnotify
Condition 对象必须从 Lock 对象获取。