Does wait() method have to be called from synchronized method or block?

Does wait() method have to be called from synchronized method or block?

Yes, It has to be. It throws IllegalMonitorStateException otherwsie.

I have explained the answer with a vanilla implementation of producer consumer problem. I have used one thread each. THe program uses a boolen flag, so the capacity is just one item. In this case let us assume if the wait in producer was called without synchronized block, then there are high chances that the consumer thread can interfere and  producer thread can go to invariable wait. This is called missing communications/signals. To avoid this, we should always call wait(), notify() and notifyAll() inside synchronized block.


import java.util.concurrent.locks.ReentrantLock;

public class MSProducerConsumer {

private volatile boolean flag = false;
ReentrantLock lock = new ReentrantLock();

void produce()
{
try
{
while(true) {
synchronized (this) {
try {
lock.lock();
while(flag)
{
System.out.println("Waiting to be consumed");
wait();
}
System.out.println("Produced");
flag = true;
notifyAll();
}
finally {
lock.unlock();
}
}
Thread.sleep(1000);
}

}
catch(InterruptedException e)
{
System.out.println("Producer interrupted...terminating");
return;
}
}

void consume()
{
try
{
while(true) {
synchronized (this) {
while(!flag)
{
System.out.println("Waiting to be produced");
wait();
}
System.out.println("Consumed");
flag = false;
notifyAll();
}
Thread.sleep(3000);
}

}
catch(InterruptedException e)
{
System.out.println("Consumer interrupted...terminating");
return;
}
}

public static void main(String[] args) {
MSProducerConsumer msProducerConsumer = new MSProducerConsumer();
Thread producer = new Thread(new Runnable() {

@Override
public void run() {
msProducerConsumer.produce();

}
});

Thread consumer = new Thread(new Runnable() {

@Override
public void run() {
msProducerConsumer.consume();

}
});

consumer.start();
producer.start();

Thread timer = new Thread(new Runnable() {

@Override
public void run() {
try {
Thread.sleep(30000);
consumer.interrupt();
producer.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
});
timer.start();
try
{
producer.join();
consumer.join();
}
catch (InterruptedException e) {
System.out.println("Threads interrupted");
}

}

}



Comments

Popular posts from this blog

Java Object Size

Analyzing Thread Dump Made Easy