Skip to content
On this page

Condition

Using ReentrantLock is safer than directly using synchronized and can replace synchronized for thread synchronization.

However, while synchronized can be used with wait and notify to make threads wait when conditions are not met and wake them up when conditions are satisfied, how can we implement the wait and notify functionalities using ReentrantLock?

The answer is to use the Condition object to achieve the functionalities of wait and notify.

Using the TaskQueue example, let's implement the functionality previously achieved with synchronized using ReentrantLock and Condition:

java
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();
        }
    }
}

As seen, when using Condition, the Condition object must be obtained from the Lock instance's newCondition() method. This ensures that the Condition instance is bound to the Lock instance.

The Condition methods await(), signal(), and signalAll() function similarly to the wait(), notify(), and notifyAll() methods of the synchronized lock object. Their behaviors are also the same:

  • await() releases the current lock and enters a waiting state.
  • signal() wakes up a single waiting thread.
  • signalAll() wakes up all waiting threads.
  • After being awakened, threads must reacquire the lock before continuing execution.

Additionally, similar to tryLock(), await() can wait for a specified period. If the thread is not awakened by another thread calling signal() or signalAll() within the specified time, it can wake up on its own:

java
if (condition.await(1, TimeUnit.SECONDS)) {
    // Woken up by another thread
} else {
    // Not awakened within the specified time
}

This demonstrates that by using Condition in conjunction with Lock, we can achieve more flexible thread synchronization.

Summary

  • Condition can replace wait and notify.
  • Condition objects must be obtained from Lock objects.
Condition has loaded