Below I have included the Producer-Consumer program (from Java - The Complete Reference Guide Ninth Edition) which is probably a familiar example of inter-thread communication to many of you.
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while(!valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
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;
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 PC {
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 would like clarification on why Producer can never modify n twice without Consumer returning. In particular, inside get, the notify(); line comes before return n;. (Of course the method must end with the return line.)
But, inside get, why can't the operating system award the lock to Producer after the line notify() and before return n?
But why is it inconceivable that the Producer thread gets to this.n = n; before the Consumer thread executes the very next return n; line, on say a single core system?
Because, both methods are synchronized
and only one thread can execute them at one time.
For your scenario, if CPU puts away consumer thread after calling notify()
and before returning n
; producer will still be waiting to acquire lock due to synchronized
keyword. Producer has become runnable after call to notify
but will not run until lock remains with consumer.