Introduction:
In Java, wait() and notify() are essential methods used for synchronization and communication between threads. Surprisingly, these methods are not declared in the Thread class, where you might expect them to be. Instead, they are found in the Object class. This blog post aims to explain the rationale behind this design choice and how to use wait() and notify() effectively. Let's dive in!
Why are wait() and notify() in the Object Class?
The decision to place wait() and notify() in the Object class rather than the Thread class is primarily due to the nature of their functionality. These methods are not thread-specific; instead, they are used to coordinate the execution of threads that are contending for the same lock (monitor) associated with an object. Here's a breakdown of the reasons:
1. Universal Access: Placing wait() and notify() in the Object class ensures that all objects in Java can participate in thread synchronization. This universal accessibility promotes better code organization and consistency across the language.
2. Fine-grained Locking: Java uses an intrinsic locking mechanism, where each object is associated with an intrinsic lock. The wait() and notify() methods are designed to work with this intrinsic lock. Having these methods in the Object class allows any object to be used as a lock and thus facilitates fine-grained locking.
3. Thread Independence: By keeping these methods in the Object class, Java avoids tying the methods directly to Thread objects. This decoupling promotes better design practices and allows multiple threads to synchronize on the same object independently.
Using wait() and notify():
To use wait() and notify() effectively, you need to follow specific patterns. First, ensure that the calling thread owns the monitor of the object before invoking wait() or notify(). Here's a sample code demonstrating how to use wait() and notify() for thread synchronization:
public class SharedResource {private boolean flag = false;public synchronized void waitForSignal() {while (!flag) {try {wait(); // Release the lock and wait for a notification} catch (InterruptedException e) {e.printStackTrace();}}// Code to be executed after receiving the notification}public synchronized void setFlagAndNotify() {// Code to update the flagflag = true;notify(); // Notify waiting threads to wake up and acquire the lock}}
In this example, two methods `waitForSignal()` and `setFlagAndNotify()` are declared within the same class, both synchronized on the same object (`this`). The `waitForSignal()` method waits for a notification (by calling wait()) until the flag becomes true, while `setFlagAndNotify()` sets the flag to true and then notifies any waiting threads (by calling notify()).
Conclusion:
Placing wait() and notify() in the Object class instead of the Thread class is a design decision that facilitates better synchronization and promotes thread independence. Understanding the proper use of these methods is crucial for writing efficient and thread-safe code. By applying the concepts discussed in this blog post, you can effectively utilize wait() and notify() to coordinate the behavior of multiple threads in your Java applications. Happy coding!