Why Must Wait() Always Be in Synchronized Block

Why must wait() always be in synchronized block

A wait() only makes sense when there is also a notify(), so it's always about communication between threads, and that needs synchronization to work correctly. One could argue that this should be implicit, but that would not really help, for the following reason:

Semantically, you never just wait(). You need some condition to be satsified, and if it is not, you wait until it is. So what you really do is

if(!condition){
wait();
}

But the condition is being set by a separate thread, so in order to have this work correctly you need synchronization.

A couple more things wrong with it, where just because your thread quit waiting doesn't mean the condition you are looking for is true:

  • You can get spurious wakeups (meaning that a thread can wake up from waiting without ever having received a notification), or

  • The condition can get set, but a third thread makes the condition false again by the time the waiting thread wakes up (and reacquires the monitor).

To deal with these cases what you really need is always some variation of this:

synchronized(lock){
while(!condition){
lock.wait();
}
}

Better yet, don't mess with the synchronization primitives at all and work with the abstractions offered in the java.util.concurrent packages.

Why is wait inside of synchronized?


  1. Synchronized keyword is used for exclusive accessing.
  2. To make a method synchronized, simply add the synchronized keyword to its declaration. Then no two invocations of synchronized methods on the same object can interleave with each other.
  3. Synchronized statements must specify the object that provides the intrinsic lock. When synchronized(this) is used, you have to avoid to synchronizing invocations of other objects' methods.
  4. wait() tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
  5. notify() wakes up the first thread that called wait() on the same object.

Example:

public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();

synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}

System.out.println("Total is: " + b.total);
}
}
}

class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}

Got it from: http://www.programcreek.com/2009/02/notify-and-wait-example/

synchronized block/method without wait() and notify() notifyAll() methods

It is mandatory that wait(), notify() and notifyAll() should always be called from within a synchronized block. But it does not mean that synchronized blocks should always have one of these methods.

Using wait() inside a synchronized block

Your statement "any number of threads can enter the synchronized block" is false.

Theoretically, if one thread is inside the synchronized block, this prevents other threads from entering. Which is not possible in the case of IntentService because IntentService uses a single worker thread to handle the workload.

Calling wait() is a thread synchronization method, not a delay method. This is different from calling sleep() which just blocks the thread for a specific amount of time. When you call wait() this blocks the thread until another thread calls notify(), which is used to coordinate activities among multiple threads. wait(10000) blocks the thread until either notify() is called from another thread OR until the timeout expires (in this case 10 seconds). So this looks like there should be another thread somewhere which is calling notify() on the IntentService object to wake it up.

There is an additional complexity here associated with the use of notify() and wait(). In order to call either of these methods, a lock on the object's monitor must first be obtained (by the use of synchronized). This means that calls to wait() and notify() must be within synchronized blocks or within synchronized methods that are synchronized on the object.

The thread that calls wait() actually releases the lock on the object. This means that the thread is blocked inside a synchronized block/method but it does not have a lock on the object while waiting. Once notify() is called (or the timeout has expired), the thread will regain the lock on the object and continue executing.

For more information about using notify() and wait() in Java, search for these terms and read about it.


This code is pretty convoluted if all it is supposed to do is delay 10 seconds and then write a something to logcat. You could just call sleep() instead of wait() which would not require the synchronized statement. However, as another poster noted, if this Service is called very often, this will create a backlog as each and every call to onHandleIntent() will be delayed by 10 seconds and since there is only 1 worker thread, all calls are serialized. Example: a call to startService() is made at 10:00:00, the entry in the logcat will appear at 10:00:10. If another call to startService() is made at 10:00:01, that entry will not appear in the logcat until 10:00:20, because the second call to onHandleIntent() will not happen until 10:00:10.

Difference between Synchronized block with wait/notify and without them?

Using synchronized makes a method / block accessible by only on thread at a time. So, yes, it's thread-safe.

The two concepts are combined, not mutually-exclusive. When you use wait() you need to own the monitor on that object. So you need to have synchronized(..) on it before that. Using .wait() makes the current thread stop until another thread calls .notify() on the object it waits on. This is an addition to synchronized, which just ensures that only one thread will enter a block/method.

If I (need to) enclose wait() and notify() calls in synchronized blocks, how can notify() ever be executed?


How

When you call wait in the synchronized block, the monitor lock will be released automatically, see the doc:

The thread releases ownership of this monitor and waits until another
thread notifies threads waiting on this object's monitor to wake up
either through a call to the notify method or the notifyAll method.
The thread then waits until it can re-obtain ownership of the monitor
and resumes execution.

After the other thread calling notify and exiting its synchronized block, the waiting thread will wake up and try aquire the monitor lock to continue.

Why

Breifly:

A wait() only makes sense when there is also a notify(), so it's
always about communication between threads, and that needs
synchronization to work correctly.

Check this for more.

why when a thread invokes d.wait, it must own the intrinsic lock for d ?


1) why "when a thread invokes d.wait, it must own the intrinsic lock for d"?

Because the javadoc says it must!

Why?

Well the primary purpose of wait and notify are to implement condition variables and the like. In general, one thread waits for some other thread to notify it that some shared state has changed. If the waiting thread didn't have to wait within a lock, then there would be no guarantee that the state changes made by the second thread would be visible ... as per the Java memory model.

You would also need to worry about races. For example, suppose a third thread that was also waiting on that same condition and got a different notification ... and only just got scheduled. Now you have two threads both checking the condition ... at the same type. (Note this only applies for some use-cases.)

2) the statement also mentioned, "otherwise an error is throw". What kind of error is thrown?

The javaoc says: "Throws ... IllegalMonitorStateException - if the current thread is not the owner of the object's monitor."


Could you please tell me under what kind of potential circumstances that 'the current thread is not the owner of the object's monitor'?

That would be when it hasn't acquired the lock by entering a synchronized block ... or equivalent.



Related Topics



Leave a reply



Submit