`

Wait和Notify的读书笔记

阅读更多

Wait和notify
Just as each object has a lock that can be obtained and released, each object also provides a
mechanism that allows it to be a waiting area. And just like the lock mechanism, the main reason for this mechanism is to aid communication between threads.[1] The idea behind the mechanism is actually simple: one thread needs a certain condition to exist and assumes that another thread will create that condition. When this other thread creates the condition, it notifies the first thread that has been waiting for the condition. This is accomplished with the following methods:

What is the purpose of the wait and notify mechanism, and how does it work? The wait and notify mechanism is also a synchronization mechanism; however, it is more of a communication mechanism: it allows one thread to communicate to another thread that a particular condition has occurred. The wait and notify mechanism does not specify what the specific condition is.

Can wait and notify be used to replace the synchronized method? Actually, the answer is no. Wait
and notify does not solve the race condition problem that the synchronized mechanism solves. As a matter of fact, wait and notify must be used in conjunction with the synchronized lock to prevent a race condition in the wait and notify mechanism itself.

The wait() method releases the lock prior to waiting, and reacquires the lock prior to
returning from the wait() method. This is done so that no race condition exists. If you
recall, there is no concept of releasing and reacquiring a lock in the Java API. The wait()
method is actually tightly integrated with the synchronization lock, using a feature not
available directly from the synchronization mechanism. In other words, it is not possible for
us to implement the wait() method purely in Java: it is a native method.

What happens when notify() is called and there is no thread waiting?
Since the wait and notify mechanism does not know the condition about which it
is sending notification, it assumes that a notification for which there is no thread waiting is a
notification that goes unheard. In other words, if notify() is called without another thread waiting, then notify() simply returns.

What are the details of the race condition that exists in wait and notify? In general, a thread that uses the wait() method confirms that a condition does not exist (typically by checking a variable) and then calls the  wait() method. When another thread sets the condition (typically by setting that same variable), it then calls the notify() method. A race condition occurs when:
1. The first thread tests the condition and confirms that it must wait.
2. The second thread sets the condition.
3. The second thread calls the notify() method; this goes unheard, since the first thread is not
yet waiting.
4. The first thread calls the wait() method.

How does this potential race condition get resolved? This race condition is resolved by the
synchronization lock discussed earlier. In order to call wait() or notify(), we must have obtained
the lock for the object on which we're calling the wait() or notify() method. This is mandatory: the methods will not work properly and will generate an exception condition if the lock is not held. Furthermore, the wait() method also releases the lock prior to waiting and reacquires the lock prior to returning from the wait() method. The developer must use this lock to ensure that checking the condition and setting the condition is atomic, which typically means that the condition is held in an instance variable within the locked object.

What happens when there is more than one thread waiting for the notification? Which thread
actually gets the notification when notify() is called? The answer is that it depends: the Java
specification doesn't define which thread gets notified. Which thread actually receives the notification varies based on several factors, including the implementation of the Java virtual machine and scheduling and timing issues during the execution of the program. There is no way to determine, even on a single platform, which of multiple threads receives the notification.

Why would you want to wake up all of the threads? There are a few possible reasons, one of which is if there is more than one condition to wait for. Since we cannot control which thread gets the notification, it is entirely possible that a notification wakes up a thread that is waiting for an entirely different condition. By waking up all the waiting threads, we can design the program so that the threads decide among themselves which should execute next.

The difference in this case is that we are calling the notifyAll() method instead of the notify()
method. There are two reasons for this:
•  It is entirely possible for the system to wake up a thread that needs more resources than are
available, even with the resources that have just been freed. If we had used the  notify()
method, another thread that could be satisfied with the current amount of resources would
not get the chance to grab those resources because the system picked the wrong thread to
wake up.
•  It is possible to satisfy more than one thread with the number of resources we have just freed.
As an example, if we free ten resources, we can then let four other threads grab three, four,
one, and two resources, respectively. There is not a one-to-one ratio between the number of
threads freeing resources and the number of threads grabbing resources.


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics