Wait () and Notify () concepts - Java multithreading

class Q { volatile boolean valueSet = false; volatile int n; synchronized int get () { if ( !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 ) { if ( valueSet ) { try { wait(); } catch ( InterruptedException e ) { System.out.println( "InterruptedException caught" ); } } this.n = n; valueSet = true; System.out.println( "Put: " + n ); notify(); } } class Producer implements Runnable { Q q; Producer ( Q q ) { this.q = q; new Thread( this, "Producer" ).start(); } public void run () { int i = 0; while ( true ) { q.put( i++ ); } } } class Consumer implements Runnable { Q q; Consumer ( Q q ) { this.q = q; new Thread( this, "Consumer" ).start(); } public void run () { while ( true ) { q.get(); } } } class PCFixed { public static void main ( String args[] ) { Q q = new Q(); new Producer( q ); new Consumer( q ); System.out.println( "Press Control-C to stop." ); } } 

I can’t understand how this works. Take this thread, for example. The manufacturer introduces the put method and calls notify (). What if wait () has not yet been called by the consumer? Also, as soon as the manufacturer calls notify (), how can the consumer introduce the get () method when the manufacturer has not yet released a monitor? Please help me here.

+3
source share
3 answers

I assume the class at the top is Q, it skips some code. In any case, the general idea is that the boolean calls valueSet and wait() / notify() work in tandem.

If the consumer has already begun to wait, he has acquired a lock on the Q instance using the synchronized get() method, and then releases it while he waits.

If the consumer has not yet begun to wait, the manufacturer may have a lock for the Q instance, because the put() method is synchronized with the same lock. As soon as the manufacturer leaves the castle, he will call notify() , and also set the valueSet parameter to boolean true.

The next consumer call get() will read the boolean before trying to wait, notice something there, take the contents of n and do any work. If the value has not been set, which means that nothing happened in the absence of the consumer, he will wait() on the lock for new work, and the next notify() wake him.

Update

In your script, in the comments, you are essentially asking about the same situation, but vice versa. The same logic is used.

Currently, the consumer is waiting, and the producer is calling notify() . The manufacturer currently has a lock and will continue to hold the lock throughout the method. All notify() really allows one other thread that is currently waiting for locks to know that when the lock is released, it can try to lock and resume execution. In this case, there is only one other thread, but if there were several threads, then it would select only one (to wake everyone, notifyAll() should be called).

  • The manufacturer exits the method, releasing the lock.
  • The consumer wakes up and takes the lock.

At this point, it is controversial as to whether the manufacturer has appeared, and is currently awaiting locks, or if it has not yet entered a method. The tandem of the Boolean flag and wait() / notify() also apply to this.

Before the consumer releases the lock, exiting the method sets the boolean flag to false and calls notify() .

If the manufacturer is currently waiting for a lock, a call to notify() will let him know that he can wake up and continue when the lock is released.

If the producer does not expect a wait() call, it must be outside the method (perhaps waiting to enter the method and get a lock in this way). When the consumer exits the method and releases the lock, the manufacturer acquires it and checks the Boolean flag. It was set to false, so the manufacturer does not try to call wait() and simply disables its value, sets the boolean flag and calls notify() .

+2
source
  • What if wait () has not yet been called by the consumer?
    • Message will be lost.
  • Once the manufacturer calls notify (), how can the consumer introduce the get () method when the manufacturer has not released the monitor yet?
    • It locks the lock until the monitor is repeatedly shown.
+1
source

I will try to understand how this works. For example, Producer introduced the put() method and saw that the monitor is free and that it can execute the put action. While he is doing his work, Consumer appears and tries to execute the get() action. But it fails because the monitor is already taken by Producer , so it calls wait() , which means it is locked in this line of code, expecting some other thread to call notify() . The trick here is that it never calls get() again before it is notified that the monitor is free again, which means it will not execute any empty loops. So, when Producer finished his work, he calls notify() , and Consumer resumes where he left off. I know that at first it is difficult to understand and a little difficult to explain, but when you do this, you will see that these are really simple and powerful things. Good luck

0
source

Source: https://habr.com/ru/post/1496755/


All Articles