class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while (!valueSet)
try {
wait();
} catch (Exception e) {
}
;
System.out.println("Pego : " n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while (valueSet)
try {
wait();
} catch (Exception e) {
}
;
this.n = n;
valueSet = true;
System.out.println("Inserido : " n);
notify();
}
}
class Producer2 implements Runnable {
Q q;
Producer2(Q q) {
this.q = q;
new Thread(this, "Geradora").start();
}
public void run() {
int i = 0;
while (true) {
q.put(i );
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer2 implements Runnable {
Q q;
Consumer2(Q q) {
this.q = q;
new Thread(this, "Consumidora").start();
}
public void run() {
while (true) {
q.get();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PCFixed {
public static void main(String[] args) {
Q q = new Q();
new Producer2(q);
new Consumer2(q);
}
}
Text from the book: Inside get(), wait() is called. This suspends the execution till Producer notify... My question is, Once I instantiate Producer and Consumer, the execution reaches put, not get. So how come it calls get first and then call wait() inside get()?
CodePudding user response:
The system can only be in one of two states:
It is empty
valueSet is false, the put method will not even once enter that while loop and thus never invokes wait(), and the get method would wait().
It is full
valueSet is true, the get method will not even once enter that while loop and thus never invokes wait(), and the put method would wait().
Explanation
Because the get and put methods are synchronized, only one can be running (and note that wait() will open the gates and let other code run. It'll re-acquire the lock before wait() actually exits - for code to go on past a wait(), both notify() must be called, and whatever called it needs to get to the end of it synchronized block/method.
The code starts off in 'empty' mode.
It doesn't matter if you attempt to invoke put and get simultaneously; these methods are synchronized on the this reference so only one can actually run, the other would freeze until the lock is available. Thus, we have two options:
The
putcall wins. In this case, the put call will immediately set the value and not wait at all, sets the mode to 'full' (valueSet = true), does a uselessnotify()that has no effect but also does no harm, and ends. Thegetcall was waiting to start and can now start. It will notwaitat all (as it is in "full" mode;valueSet == true), gets the value and prints it, sets the mode back to empty, does another useless notify, and exits.The
getcall wins. In this case, thegetcall will enter the while loop and waits. This releases the lock, which means theputcall can now go. It will not wait at all (as thewhileloop's condition is false, which means it runs zero times), it sets a value, andnotify()- that 'releases' theget()call which now merely waits for the lock to be available to continue. Theputmethod ends, thus releasing the lock. The get call continues and fetches the value. It then does a useless notify, and exits as well.Instead you attempt to run 2 put calls simultaneously. One wins and immediately sets as usual, then the other runs and will immediately enter
waitmode and will be stuck there (as will any furtherputcalls, they all run into thewait()call and wait there), until you callget()in some thread, this will get a value, set the thing to be in 'empty' mode, and notifies one arbitrary thread, thus unlocking it. It will put its value and set your object back to "full" mode and exit, leaving the other putters still waiting around. Another get call would immediately proceed, fetch it, notify another one of the waitingputcalls, and so on.
CodePudding user response:
Because both Producer2 and Consumer2 create a new thread in their constructors.
So calling
new Producer2(q);
In the main method, doesn't stop the execution, it goes immediately to the next line which is
new Consumer2(q);
Which is where the call to q.get happens
