0
public class class_Q {
volatile boolean valueSet = false;
volatile int n;



synchronized int get()
{  
System.out.println("Now i am in get block and  valueset is : "+ valueSet  );
    if(!valueSet)
    {
        System.out.println("i am waiting in get block.....and releasing lock  ");
    try{
        wait();
    }catch(InterruptedException e)
        {
    System.out.println( "InterruptedException caught" );
        }
    }
    System.out.println( " value of n now in get block is  : " + n );
    valueSet=false;
    notify(); 
    return n; 
}


   synchronized void put(int n)
     {  
System.out.println(" Now i am in Put block and  valueset is : "+ valueSet);
if(valueSet) 
{
try
{
System.out.println("i am waiting in put block......and releasing lock. ");
wait();
}catch(InterruptedException e)
{
System.out.println( "InterruptedException caught" );
}
}
  this.n = n;
  valueSet = true;
  System.out.println( "the value of n now in put block is : " + n );
  notify();   
  }

}

 class Producer implements Runnable{
class_Q q;
Producer(class_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{
class_Q q;
 Consumer(class_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[])
{
    class_Q q = new class_Q();
    new Producer(q);
    new Consumer(q);
    System.out.println( "Press Control-C to stop." );   
    }
} 

*OUTPUT**

Now i am in get block and valueset is : false

i am waiting in get block.....and releasing lock

Press Control-C to stop.

Now i am in Put block and valueset is : false

the value of n now in put block is : 0

the value of n now in get block is : 0

Now i am in get block and valueset is : false

i am waiting in get block.....and releasing lock

Now i am in Put block and valueset is : false

the value of n now in put block is : 1

the value of n now in get block is : 1

After sixth line of my output i am expecting get() thread to wake up (" notify() " ) put() thread. can someone help me understand the logic behind calling get() thread (in other words why it is in get block?)

MKod
  • 803
  • 5
  • 20
  • 33
  • 1
    Format your code if you want any chance of us reading it. Your code is a mess. Especially try to follow the "brace same line" style, which uses a lot less lines and that's important on a web screen, even though anal people seem to think it's necessary to put new lines everywhere. – Bohemian Jun 01 '12 at 11:57
  • `in other words why it is in get block?` do you mean why notify is in get block? – UmNyobe Jun 01 '12 at 12:32

3 Answers3

1

I have reformatted your code and changed the logging messages so all should be much clearer.

public class Test {
  static class class_Q {
    volatile boolean valueSet = false;
    volatile int n;

    synchronized int get() throws InterruptedException {
      System.out.println("get entering - valueSet=" + valueSet);
      // *** Changed from `if` to `while`
      while (!valueSet) {
        System.out.println("get waiting");
        wait();
      }
      // Clear to set the value.
      valueSet = false;
      // Tell any put waits to finish
      notify();
      System.out.println("get finished - n=" + n);
      return n;
    }

    synchronized void put(int n) throws InterruptedException {
      System.out.println("put entering - valueSet=" + valueSet);
      // *** Changed from `if` to `while`
      while (valueSet) {
        System.out.println("put waiting");
        wait();
      }
      this.n = n;
      valueSet = true;
      System.out.println("put finished - n=" + n);
      notify();
    }
  }

  static class Producer implements Runnable {
    class_Q q;

    Producer(class_Q q) {
      this.q = q;
    }

    public void run() {
      int i = 0;
      try {
        while (true) {
          q.put(i++);
          System.out.println("put(" + (i-1) + ")");
        }
      } catch (InterruptedException ex) {
        // Just exit the run loop and finish when interrupted.
      }
    }
  }

  static class Consumer implements Runnable {
    class_Q q;

    Consumer(class_Q q) {
      this.q = q;
    }

    public void run() {
      try {
        while (true) {
          int i;
          i = q.get();
          System.out.println("get(" + i + ")");
        }
      } catch (InterruptedException ex) {
        // Just exit the run loop and finish when interrupted.
      }
    }
  }

  public static void main(String args[]) {
    class_Q q = new class_Q();
    Thread producer = new Thread(new Producer(q));
    Thread consumer = new Thread(new Consumer(q));
    System.out.println("Press Control-C to stop.");
    producer.start();
    consumer.start();
  }
}

I have made three main changes too. I have made the interrupted mechanism just quit your threads. I have made your blocking tests loop on the blocked state, not just check them (while (x) instead of if (x)). I have made your threads NOT auto-start.

I think if you run this code now the processes should be clearer and you should be able to understand better what is happening. Remember that System.out is a PrintWriter and can therefore be buffered.

The output I get is:

put entering - valueSet=false
put finished - n=0
put(0)
put entering - valueSet=true
put waiting
Press Control-C to stop.
get entering - valueSet=true
get finished - n=0
put finished - n=1
put(1)
put entering - valueSet=true
put waiting
get(0)
get entering - valueSet=true
get finished - n=1
put finished - n=2
put(2)
put entering - valueSet=true
put waiting
get(1)
get entering - valueSet=true
get finished - n=2
get(2)
get entering - valueSet=false
get waiting
put finished - n=3
get finished - n=3
get(3)
get entering - valueSet=false
get waiting
put(3)
put entering - valueSet=false
put finished - n=4
get finished - n=4
get(4)
get entering - valueSet=false
get waiting
put(4)
...
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • thank you for the modifications. I am struggling to understand why execution is still in PUT block after 3rd line of the above output. as soon as " System.out.println("put finished - n=" + n); " executed the line of code execution should be in GET block .because notify() will wake up GET block to start executing. ....... My understanding is NOTIFY() 's job is to wake up thread that is in waiting. – MKod Jun 03 '12 at 10:13
  • Please correct me if I am wrong. 1) Notify () doesnt do nothing if there is no thread waiting? – MKod Jun 03 '12 at 10:57
  • You are correct, but it is even stranger than that. 1) notify will not do anything if no thread is waiting on the object 2) even if notify does find a waiting thread, all it will do is ALLOW it to proceed ... it may not proceed immediately and it often will not. You will commonly find that the most likely place for a thread to resume is when another threads waits. – OldCurmudgeon Jun 03 '12 at 14:42
  • If you add `System.out.println("get woke up");` after the `wait` in `get` (and the equivalent in `put`) things may become more clear. – OldCurmudgeon Jun 03 '12 at 14:46
  • And finally note (see the `Press Control-C to stop.`) that the order of the logging statements does not necessarily reflect the order of the execution of the processes in a parallel system. – OldCurmudgeon Jun 04 '12 at 00:36
0

After sixth line of my output i am expecting get() thread to wake up (" notify() " ) put() thread. can someone help me understand the logic behind calling get() thread (in other words why it is in get block?)

Producer start, call put, valueSet is false, return from the function, and call put again, valueSet is true so he has to wait... Without a notify in get, then Producer is blocked forever, even if the Consumer has read the written value...

The notify in each is used to signal the other participant which was ahead in the process and which was waiting for the thread which was behind that they are now both as the same spot.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90
0

This is classic producer-consumer pattern with blocking queue. Produces writes data to queue and blocks if queue is full (in current implementation size of queue - single element). Consumer reads from queue and blocks (wait) while queue is empty.

1 You calling get() with valueSet = false. It is stops at wait().

2 You calling put() that notify() your queue object and unlock execution of thread that wait in get() method.

alexey28
  • 5,170
  • 1
  • 20
  • 25