theimpatientcoder
theimpatientcoder

Reputation: 1098

Confusion on Wait ,Notify and Sleep

I have a simple program which I am finding very confusing. The code snippet is as follows:

 class Processor{

      public void produce() Throws InterruptedException{
          synchronized(this){ 

              System.out.println("Producer Running...");
              wait();
               System.out.println("Resumed");

          }
      }


     public void consume() Throws InterruptedException{
          synchronized(this){ 
              Thread.Sleep(2000);
              System.out.println("Consumer Running... Press return key to return");
              scan.nextLine();                
              notify();  
              Thread.sleep(5000);

          }

 }

Now my question is that , when we call wait() in the "produce" method the execution is immediately transferred to the "consume" method. (produce and consume are executed in separate threads). But when the notify(); is called in the "consume " method ,the execution does not immediately transfer. It waits for Thread.sleep(5000) to complete . why is this so ?

Upvotes: 1

Views: 940

Answers (4)

Lolo
Lolo

Reputation: 4347

The reason is that Thread.sleep(5000L) does not release the lock on the object's monitor while it's waiting, contrary to wait(5000L). This is specified in the Javadoc for Thread.sleep() :

... The thread does not lose ownership of any monitors.

Whereas the javadoc for Object.wait() specifies:

... This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object...

Upvotes: 0

Victor
Victor

Reputation: 3978

Assuming that you are calling both methods using the same object from difference threads.

If you want to don't wait 5000 miliseconds, use wait(5000) instead of Thread.sleep(5000).

The notify method, take one (random) previously waiting thread, that is waiting to acquire the lock (of an object) that the running/current thread has taken before, and mark it to resume as soon the current thread release the lock.

In your this case, it will release the lock and soon the Thread.sleep(5000) finish and leave the synchronized block.

Be aware, if you call produces or consume with diferents objects things will go totally diferent. I strongly suggest to read this article.

Hope it helps! As the good answers below!

Upvotes: 0

awksp
awksp

Reputation: 11867

Although you seem to be missing some code needed for me to explain completely accurately, I'll do my best to provide an explanation that would be applicable even if my guess was incorrect.

wait() and notify() are methods called on a mutex object -- in this case, this.

wait() causes the currently executing thread to pause and give up that mutex (I think it's just the mutex that wait() is called on, could be all of them. Not sure), after which another thread can acquire the mutex and start executing. This is why you observe an immediate transfer of control when wait() is executed.

When notify() is called on a mutex, a thread waiting on that mutex wakes up and attempts to acquire the lock. However, it cannot do so until the lock is available -- in this case, until the lock (this) is released by the thread that calls notify() (the consumer thread). The mutex is only released once the consumer thread exits from the synchronized block, which is after the Thread.sleep(5000); call in your code. sleep() does not release any mutexes that the current thread has acquired, so the first thread has to wait until the second has finished sleeping and exited the synchronized block.

That is why wait() transfers control immediately, while notify() (in this case) has the currently executing thread finish its method before the formerly waiting thread can continue execution.

Upvotes: 2

Claudio
Claudio

Reputation: 1858

Well, the reason is quite simple.

When a thread calls wait() on certain object it goes into a waiting state and it stops executing (it is removed from scheduling). When waiting a thread releases all the monitors it has taken (and it needs to regain them after waking up)

When a thread calls notify() on certain object it wakes up another thread waiting over it, but it does not go into a waiting state itself, so it keeps running.

After your producer thread calls notify it keeps running and performing a five seconds sleep. While sleeping a thread retains all monitors that it has taken (you are inside a synchronized(this) block hence you have a monitor for "this" object). Scheduler cannot run the consumer thread that was just notified since it needs to readquire the monitor before resuming, and it wont be freed until your producer thread stops sleeping and gets out of the synchronized block

Upvotes: 4

Related Questions