I'm trying to figure out how to use wait & notify, so I've written this small example with a few planes waiting for a runway to clear before they take off, the issue I'm having is that when a plane takes off, and calls notifyAll(), only one thread seems to be woken up, i.e. I expect all of the threads to report that they have been notified, but are still waiting. What actually happens is that only one thread is woken, and the rest do nothing. Why does it appear that only the one thread is woken, and how can I fix it?
class Plane extends Thread
{
Runway runway;
Plane(int id, Runway runway)
{
super(id + "");
this.runway = runway;
}
public void run()
{
runway.taxi();
runway.takeoff();
}
}
class Runway
{
boolean isFull;
Runway()
{
isFull = false;;
}
public synchronized void taxi()
{
System.out.println(Thread.currentThread().getName() + " started to taxi");
while(isFull)
{
System.out.println(Thread.currentThread().getName() + " is queued");
try
{
wait();
}
catch(InterruptedException e){}
}
isFull = true;
System.out.println(Thread.currentThread().getName() + " entering runway");
}
public synchronized void takeoff()
{
try
{
Thread.currentThread().sleep(1000);
}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName() + " took off");
isFull = false;
notifyAll();
}
public static void main(String[] args)
{
Runway runway = new Runway();
new Plane(1, runway).start();
new Plane(2, runway).start();
new Plane(3, runway).start();
new Plane(4, runway).start();
}
}
Thanks for taking the time to help me :)
Because notifyAll() is not wakeAll(). All threads are notified, but only one gets hold of the key and is being run. All others get to waiting pull again.
Suppose you have 4 Planes that are all start()-ed one after the other.
All 4 will attempt to call taxi() followed by takeoff()
The first one will call taxi():
acquire the lock,
find isFull is false
set isFull to true
return, releasing the lock
Then one (or more) of the remaining threads may get to call taxi(). If they do, they:
acquire the lock
find isFull is false
call wait() which releases the lock
OR
block while trying to acquire the lock
In the mean time, the thread that returned from taxi() will call takeoff(). This will:
acquire the lock
sleep for 1 second,
notify any threads that were waiting
return, releasing the lock.
So how does this explain what you are seeing?
Suppose that when the first thread returned from taxi() it was immediately able to reacquire the lock and start the takeoff() call. It would then call sleep() WHILE HOLDING THE LOCK. This would prevent any other threads from starting their taxi() calls (if they hadn't already done so). Then after the sleep, it would call notifyAll(). But that would only notify the threads that were had gotten into the taxi() call and that had called wait(). Any threads that were blocked while starting the taxi() call would never see the notifications.
(Notifications are never queued for threads that are not in wait() calls.)
Is this likely? Well yes it is.
Starting a thread is a relatively expensive / time consuming process, and there is a good chance that the first thread started will get to do a lot of work before the next one gets started. The chances are that it will get all the way to the sleep call before the second one tries to call taxi().
The same pattern is likely to repeat for the remaining threads. When each thread that gets into taxi() is likely to release and then reacquire it before another thread is scheduled. (Thread scheduling is handled by the OS, and it is optimizing for efficiency rather than fairness. If you want fair scheduling, you need to use a Lock object.)
... how can a fix it?
Change your code so that you don't sleep while holding the lock. For example:
public void takeoff() {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// squash ...
}
System.out.println(Thread.currentThread().getName() + " took off");
synchronize (this) {
isFull = false;
notifyAll();
}
}
That's what it does. It "notifies" all the waiting threads, but only one wakes and gets the CPU. notify() picks a waiting thread based on what the underlying thread implementation selects. notifyAll() gives all the waiting threads an equal chance to compete. But either way, only one thread takes the context.
Related
This question was asked to me in an interview. Before I had told him this,
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
Consider the snippet:
Q1:
public class Q1 {
int n;
boolean valueSet = false;
synchronized int get() {
while (!valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while (valueSet)
try {
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
Producer1:
public class Producer1 implements Runnable {
Q1 q;
Producer1(Q1 q) {
this.q = q;
new Thread(this, "Producer").start();
}
#Override
public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}
Consumer1
public class Consumer1 implements Runnable {
Q1 q;
Consumer1(Q1 q) {
this.q = q;
new Thread(this, "Consumer").start();
}
#Override
public void run() {
while (true) {
q.get();
}
}
}
PC1:
public class PC1 {
public static void main(String args[]) {
Q1 q = new Q1();
new Producer1(q);
new Consumer1(q);
System.out.println("Press Control-C to stop.");
}
}
So, he asked as soon as you have created this thread new Producer1(q), then according to you, the synchronized int get() method must have been locked by the same thread, i.e, by new Producer1(q) when it accessed synchronized int put(). I said yes.
But I checked in eclipse, get is callable by new Consumer1(q). The program works perfect.
Where am I going wrong?
O/P:
The call to wait() will release the monitor for the time waiting.
That's what is documented for Object.wait():
The current thread must own this object's monitor. 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.
Once a thread enters any synchronized method on an instance, no other
thread can enter any other synchronized method on the same instance.
What you forgot to add here is "except if the lock is released".
...and it is the case in your example, when calling wait.
The documentation specify :
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.
Since the lock is released, you step in the other method (and the condition is true because the boolean was modified). Once in the other method, you release the lock again, then call notify and you wake up the old thread which terminates (re-modify boolean to pass the condition in other method, and notify). That way you step between both methods ad-infinitum.
wait() and notify() is acts as a signal between threads, to control the threads to do or to not do the stuff.
The program works perfect because here 2 threads (Producer, Consumer) which fight for the one lock (monitor). When Consumer aquires the lock (Q1 object) then Producer is waiting for the lock. When Consumer finishes his work it release the lock. Consumer releases the lock also when wait() method has been called, because wait() sets thread to Waiting state with lock release. It's time for Producer to aquire the lock and does his work. When Producer thread notify() calls then Consumer continue his work (when aquired the lock). The same is right for Producer.
Resume: Q1 object is a lock for all threads. If it aquired someone then others are blocked and the answer is - it not possible to get an access at the same time to the get(), put() methods more then 2 threads.
I think that the question is ambiguous. (E.g., what does "accessible" mean?)
IMO, a good interview question should not have a right answer and a wrong answer. A good interview question should be a conversation starter, that gives you an opportunity to show how much you know about the subject.
When I am asking the interview questions, I like a candidate who can see through the question, and get down to the underlying mechanism. E.g.,
What the JLS guarantees is that no two threads can be _synchronized_
on the same instance at the same time...
Then we could explore questions like, how could two threads enter the same synchronized method at the same time? (e.g., synchronized on different instances), how could two threads be in the same synchronized method for the same instance at the same time (one of them could be in a wait() call), ...
A thread can not access a synchronized block of code unless it has aquired a lock on the object that guards the block. In your case, the synchronized keyword uses the lock of the object in which it has been declared. So as long as a thread is executing get(), no other thread can execute the put().
If you apply this, when put() sets the value, it notifies consumer which accepts the value. The code should work even after you have removed the wait() and notify() calls from both get and put methods
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
ExampleTest obj = new ExampleTest();
Thread t1 = new Thread(new Runn(obj));
Thread t2 = new Thread(new Runn(obj));
Thread t3 = new Thread(new Runn(obj));
t1.start();
t2.start();
t3.start();
//Thread.sleep(1);
obj.exit();
}
}
class ExampleTest {
public synchronized void enter() {
try {
System.out.println("printed " +Thread.currentThread().getName() +" inside wait");
this.wait();
System.out.println("printed " +Thread.currentThread().getName() +" exit wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("printed " +Thread.currentThread().getName() +" at time: "+System.currentTimeMillis());
}
public synchronized void exit() {
this.notifyAll();
}
}
class Runn implements Runnable {
ExampleTest obj;
public Runn(ExampleTest obj) {
this.obj = obj;
}
#Override
public void run() {
obj.enter();
}
}
what is the role of notifyAll(). Will notifyAll() allows all the waiting thread to acquire lock sequentially in random order or only one thread can acquire the lock?
Without the sleep statement the statement obj.exit(); will be very likely be executed before all of your threads reaching their wait status. ie. the notifyAll call will be over before at least one of your thread is in wait status. So at least one of your threads will be stuck in wait status waiting for some other thread to notify it and wake up. But that will never happen as obj.exit() is already finished.
With your sleep statement in place , all of your threads will get a chance to reach their wait status and your notifyAll call after the sleep will wake them all, The order of waking up will not be deterministic and will be handled by the thread scheduler.
Your code suffers from the "lost notification" syndrome, which is alleviated (but not deterministically avoided) by the sleep call.
You haven't provided any mechanism which would ensure that, at the time of calling exit, all the threads have already reached their wait call. Therefore some threads will miss the notification and enter an eternal wait state.
The notifyAll call does wake up all waiting threads, but it doesn't wake up threads which enter the wait state in the future.
With the following code:
t1.start();
t2.start();
t3.start();
You are starting the threads. Starting threads might take some time as it involves memory allocation and other operations. When your threads run they enter a wait state. Started threads do not, however, execute immediately. They start executing as soon as the scheduler decides it is time for them to execute. When you call start the main thread is currently running on the CPU. Without the sleep most likely the main thread will keep the CPU and call:
obj.exit();
Before the threads actually started, that is, before the threads actually entered the wait state. The notifyAll will execute in vain, as threads are not started yet and therefore are not waiting. The notification will be lost.
With the sleep call you are suspending the main thread for quite some time (for the CPU perspective). This means that the other threads will most likely get the CPU and enter the wait state. So when you then call notifyAll this time the notification will not get lost. Notice that there is no guarantee that this will happens: it might still happen that when you call exit() some (or all) other threads have not yet executed their wait.
According to the basic definition of synchronized method from source - link
"When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object."
and I read about the wait() that it releases a lock before it sleeps. There is a confusion here if wait releases the lock then other thread can get-into the synchronized method and does it make sense because it may lead to race condition?
Here is my sample code that is allowing one and two thread into the synchronized block.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Ashish Pancholi
*/
public class Test {
public Test() {
Sharing sharing = new Sharing();
Worker worker_ = new Worker(sharing);
Thread thread_ = new Thread(worker_, "one");
Worker worker = new Worker(sharing);
Thread thread = new Thread(worker, "two");
thread_.start();
thread.start();
}
public static void main(String[] argu) {
Test test = new Test();
}
public class Worker implements Runnable {
private Sharing sharing;
public Worker(Sharing sharing) {
this.sharing = sharing;
}
#Override
public void run() {
sharing.check();
}
}
public class Sharing {
public void check() {
synchronized (this) {
System.out.println("Thread IN " + Thread.currentThread().getName());
try {
wait(5000);
} catch (InterruptedException ex) {
}
System.out.println("Thread OUT " + Thread.currentThread().getName());
}
}
}
}
Output-
Thread IN one
Thread IN two
Thread OUT one
Thread OUT two
Yes it makes sense.
The API of the wait() method says:
Causes the current thread to wait until either another thread invokes
the notify() method or the notifyAll() method for this object, or a
specified amount of time has elapsed.
So if the wait method would NOT release the lock on the monitor object, no other thread could get it and thus no other thread could invoke notify or notifyAll on that monitor object.
The wait(5000) means that the current thread will wait up to 5000 milliseconds for a notification before continuing or continue after 5000 ms. If you want to hold the lock and pause 5000 ms then you must use Thread.sleep(5000).
It makes sense that there might be race conditions. Race conditions naturally happen when dealing with multiple threads. It is your job to prevent them by carefully managing your threads, and the wait method is an important tool that you can use to help with that.
Normally you wouldn't simply call wait with a fixed 5-second pause like that. In a real application you would probably be waiting for some specific condition to be true, so your wait looks more like this:
try {
while(!condition) {
wait();
}
doSomething();
} catch(InterruptedException e) {
doSomethingElseWhenWeAreAskedNotToWait();
}
Whether you have a race condition depends upon when condition becomes true, who else might be waiting for that condition, and what everyone does when it happens. The reason wait gives up the lock is to give condition a chance to become true while we wait.
You are using synchronized with two different locks, so there is no synchronization happening between the two threads.
Synchronize on the instance of Test rather than Sharing, and the behaviour will be quite different.
I'm trying to write a Java program that uses threads. I want to be able to run 3 threads when the program starts, and have them waiting on an ArrayList of "work orders".
Initially, theere will be no work orders. So the Threads should just wait.
At some point in the future, work orders will be added to the ArrayList, and the main thread must notify the threads that there is work to do.
I want to be able to do it by extending Thread (instead of implementing Runnable).
I think the main issue I have is that the threads are not correctly synchronized with the workorders ArrayList.
My code looks like this:
public static void main(String[] args) {
AnotherRunnable anotherRunnable = new AnotherRunnable();
ArrayList<ATMRunnable> workOrders = new ArrayList<ATMRunnable>();
T1 t1 = new T1(anotherRunnable, workOrders);
T1 t2 = new T1(anotherRunnable, workOrders);
t1.start();
t2.start();
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
synchronized (workOrders){
System.out.println(t1.getState() + " - " + t1.getName());
System.out.println(t2.getState() + " - " + t2.getName());
System.out.println("notify");
workOrders.notify();
System.out.println(t1.getState() + " - " + t1.getName());
System.out.println(t2.getState() + " - " + t2.getName());
}
}
The AnotherRunnable class:
public class AnotherRunnable implements Runnable {
public void run()
{
System.out.println("AnotherRunnable");
}
}
And the Tread class:
public class T1 extends Thread {
AnotherRunnable anotherRunnable;
ArrayList<ATMRunnable> workOrders;
ATMThread(AnotherRunnable anotherRunnable, ArrayList<ATMRunnable> workOrders)
{
this.anotherRunnable = anotherRunnable;
this.workOrders = workOrders;
}
public void run()
{
System.out.println("Run Thread");
synchronized (workOrders){
try{
System.out.println("wait Thread");
workOrders.wait();
}
catch (InterruptedException e){}
}
}
}
This is the output of the program:
Run Thread
wait Thread
Run Thread
wait Thread
WAITING - Thread-1
WAITING - Thread-2
notify all
BLOCKED - Thread-1
WAITING - Thread-2
As you can see, the state of the first thread is changed to Blocked, after the call to notify on the workOrders object. But neither the threads nor the runnable object is executed.
Any help will be appreciated.
You should use concurrent collections in java to avoid manual synchronization as far as possible.
I want to be able to run 3 threads when the program starts, and have them waiting on an ArrayList of "work orders". Initially, theere will be no work orders. So the Threads should just wait. At some point in the future, work orders will be added to the ArrayList, and the main thread must notify the threads that there is work to do.
For this kind of synchronization, Blocking queues are your friends like LinkedBlockingQueue which make threads wait when there's no item in the queue or when the queue is full. You do not need any synchronized/wait/notify there.
You can also check if it helps: synchronization is risky
If it is only for learning purpose, you have to make your synchronization proper first logically. It doesn't use any condition for waiting or notifying which is problematic. It'll work if it is proper but its not a preferred way.
I found what I had to do to get this working. Mainly, it was the concept what was missing. I had to loop in the run method of the thread. I was thinking that that method would be called every time notifyall is invoked, which is not true. When wait() is call on the synchronized object, the thread is stopped, and with notify it resumes execution, if that code is not in a loop, it wont be executed.
I know that there are a few threads open regarding this topic, but I'm just looking for a VERY ELEMENTARY example of how to use wait() and notify() in Java. By "VERY ELEMENTARY," I mean simply printing something out. Thanks.
EDIT: Here's what I have tried thus far and I get an IllegalMonitorStateException:
public void waiting() {
for(int i = 0; i < 10; i++) {
if(i == 5)
try {
this.wait();
} catch (InterruptedException e) {
}
else
System.out.println(i);
}
System.out.println("notify me now");
this.notify();
}
wait and notify are used in synchronized block while using threads to suspend and resume where left off.
Wait immediately looses the lock, whereas Nofity will leave the lock only when the ending bracket is encountered.
public class Mythread implements Runnable{
public synchronized void goo(){
System.out.println("Before Wait");
wait();
System.out.println("After Wait");
}
public synchronized void foo(){
System.out.println("Before Notify");
notify();
System.out.println("After Notify");
}
public class Test{
public static void main(String[] args){
Thread t = new Thread(new Mythread);
t.start();
}
}
Your IllegalMonitorStateException is due to the fact that you must synchronize on the object before calling wait or notify. So
this.wait
needs to be
synchronized(this) {
this.wait();
}
Your example won't run because you'll never get to the notify call... as soon as your thread hits wait, it will suspend and advance no further. For wait / notify to work, you have to have two threads. One thread suspends when the wait method is invoked, and eventually, the second thread calls synchronized(this) { this.notify() } to cause the first thread to wake up and continue executing below the wait call.
The synchronization is required because you would ordinarily check some condition before waiting, ie,
synchronized(this) {
if(! this.isReady) {
this.wait();
}
}
You need to synchronize to make sure no other thread changes the state of the isReady flag between the line where you check the variable and the line where you wait. So your notify code would
synchronized(this) {
isReady = true;
this.notify();
}
Now the order of the method calls doesn't matter. If you notify first, no thread will wake up, but that's ok, because you aren't going to sleep since isReady = true. If you go to sleep first, isReady = true does nothing, but the notify call wakes up the thread. Finally, the synchronization ensures that you don't check the variable in thread A, then have thread B set the variable and notify (doing nothing), then have thread A go to sleep and never wake up.
Hope that helps.
wait() and notify() are used to synchronise threads: a thread can be told to wait(), and will not continue doing anything until it receives the notify() call.
The basic idea with these functions is that wait() suspends a thread (puts it to sleep), and notify() causes a thread to pick up where it left when it went to sleep.
Take a look at: this or just look up simple prodcuer consumer problem java on google. I am sure you will find something to suit your needs.
See this example on guarded blocks from the oracle java site - it includes a worked example of a simple producer-consumer problem.