How will notifyAll work in this scenario? - java

Here is the small snippet of multi-threaded queue I wrote,
synchronized void add(int i) {
if (count == size) {
System.out.println("******full***");
isQueueFull = true;
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("adding number: " + i);
val[end++] = i;
count++;
if (isQueueEmpty) {
isQueueEmpty = false;
this.notifyAll();
}
}
synchronized int remove() {
if (count == 0) {
isQueueEmpty = true;
System.out.println("******empty***");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int t = val[0];
for (int i = 0; i < end - 1; i++) {
val[i] = val[i + 1];
}
val[end - 1] = -1;
end--;
count--;
if (isQueueFull) {
isQueueFull = false;
this.notifyAll();
}
System.out.println("removing number: " + t);
return t;
}
Lets say I have four threads adding to the queue and one thread removing from the queue. At one point,say array get full and I call wait on all four threads adding to the queue.
Now when an element gets removed, I need to call notifyAll on all of the sleeping threads.(It is giving me an arrayOutofBound exception) My questions is this, what is the flow of threads like in case of notifyAll.
Since add is synchronized method, there can only be one thread execution in it. But because of wait, we have now four threading sleeping inside it. So on notifyAll, will all four threads still be inside the add method(despite it being a synchronized method) and execute? or will it done one by one sequentially, with all of the threads being locked until one thread is completed.
It is very difficult for me to debug it in eclipse. I have a work around for arrayOutOfBoundException by putting a return statement after wait, but I would still like to understand the flow in case of notifyAll?

Waiting is very different from sleeping. The javadoc of wait() explains it:
The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
(emphasis mine)
BTW, it also contains a strong rule that you're not respecting:
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
So, when notifyAll() is called, the 4 threads compete to get back the monitor. Each one gets it back once the previous one has released it, and continues executing.

Related

Need to clear my mind on methods wait() e notify();

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()?
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 put call 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 useless notify() that has no effect but also does no harm, and ends. The get call was waiting to start and can now start. It will not wait at 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 get call wins. In this case, the get call will enter the while loop and waits. This releases the lock, which means the put call can now go. It will not wait at all (as the while loop's condition is false, which means it runs zero times), it sets a value, and notify() - that 'releases' the get() call which now merely waits for the lock to be available to continue. The put method 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 wait mode and will be stuck there (as will any further put calls, they all run into the wait() call and wait there), until you call get() 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 waiting put calls, and so on.
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

notifyAll in java

Is it wrong to use notifyAll() inside the loop in a multiple producer-consumer problem in Java?
Here is the code snippet which I am talking about.
public void run() {
while(producer_counter <= 64) {
synchronized(list) {
threadId1 = "Producer " + Thread.currentThread().getName();
//Buffer size is 8
while(list.size() >= 8) {
System.out.println( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println(threadId1+ " found the buffer is full & waiting for a Consumer to consume.");
System.out.println( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
try {
list.wait();
list.notifyAll();
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
System.out.println(threadId1+ " produced item " + producer_counter);
//Adding the items produced to the list.
list.add(producer_counter);
producer_counter++;
//Invoking notify
list.notifyAll();
}
}
}
}
notifyAll() is to notify all parties about changes in the state of the synchronized object. The first call, which is after wait(), is redundant because no state change happened. This call does not make the program wrong, but only causes waste of CPU cycles: when the buffer is full, notifyAll() is called and all other threads, waiting for the buffer's availability, go to processor only to call notifyAll() again and then call wait(). As a result, one processor in your machine will be always busy making unnecessary work.
BTW, you should not catch InterruptedException (or any other exception) if you don't know why it happened and what to do about it. If, like here, you cannot write public void run() throws InterruptedException, then write
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
Instead of RuntimeException, better declare your own unchecked exception.
You should not use list.notifyAll() in while loop.After adding the items produced to the list list.add(producer_counter) you can use notify all.
// producer thread waits while list is full
while (list.size() >= 8){
list.wait();
}
// to insert the jobs in the list and plus 1 the counter
list.add(producer_counter);
producer_counter++;
// notifies the consumer threads that now it can start
//consuming
list.notifyAll();

What does it mean to return a value after calling wait()?

In the code below I have a question regarding what happens after I call wait(). In my code, I am returning a value after calling wait(), what does this actually do? I thought that calling wait() suspends the current thread, but what happens to the value i passed to addWorkItem(Integer i) if wait() is called without returning false? You can see in the producer thread that it adds i to a retry buffer if it couldn't be added to the deque. If I don't return false after wait, does the value i just get lost, or is it still there once the thread wakes up?
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
public class ConsumerProducer2 {
private static int QUEUE_SIZE = 10;
private Deque<Integer> queue = new ArrayDeque<Integer>(QUEUE_SIZE);
public synchronized boolean addWorkItem(Integer i) {
while (queue.size() >= QUEUE_SIZE) {
try {
wait();
return false; // WHAT HAPPENS HERE?
} catch (InterruptedException ex) {}
}
queue.addLast(i);
notify();
return true;
}
public synchronized Integer getWork() {
while (queue.size() == 0) {
try {
wait();
return null; // WHAT HAPPENS HERE?
} catch (InterruptedException ex) {
}
}
Integer i = queue.removeFirst();
notify();
return i;
}
public static void main(String[] args) {
new ConsumerProducer2().go();
}
public void go() {
ConsumerThread ct = new ConsumerThread();
ct.start();
ConsumerThread ct2 = new ConsumerThread();
ct2.start();
ProducerThread pt = new ProducerThread();
pt.start();
}
class ConsumerThread extends Thread {
public void run() {
while(true) {
Integer work = getWork();
if (work == null) {
} else {
System.out.println("Thread: " + this.getId() + " received work: " + work);
}
}
}
}
class ProducerThread extends Thread {
private List<Integer> retryList = new ArrayList<Integer>();
public void run() {
while(true) {
Integer currWork;
if (retryList.size() == 0) {
currWork = (int) (Math.random() * 100);
} else {
currWork = retryList.remove(0);
System.out.println("Thread: " + this.getId() + " retrying old work: " + currWork);
}
if (!addWorkItem(currWork)) {
System.out.println("Thread: " + this.getId() + " could not add work (because buffer is probably full): " + currWork);
retryList.add(currWork);
} else {
System.out.println("Thread: " + this.getId() + " added work to queue: " + currWork);
}
}
}
}
}
Having the producer maintain a retry buffer does keep the i value from getting lost, but this still isn't a good way to write the method.
Returning from inside the while loop doesn't make sense. You check the size of the queue, and if it's maxed out you wait around until you get a notification that the size of the queue changed, then inexplicably return false (??). The waiting doesn't really accomplish anything.
The point of waiting in addWorkItem is to delay your thread until the queue has room for the new value. You should wait inside a loop, where when you come out of the wait, your thread reacquires the lock and re-checks the condition (queue size > max) to see if it can add the item yet.
Once the thread has exited from the while loop it is holding the lock, it is sure there's enough room in the queue for the new item (because no other threads can do anything to change the size of the queue while this thread has the lock held), and it can go ahead and add the value to the queue.
You are catching the InterruptedException in an unproductive way, because you catch it, don't bother to restore the interrupt flag, and go back to the top of the while loop. You should be using the interruption to quit waiting and get out of the method. Letting InterruptedException be thrown here would make more sense; the thread running the method should know better how to handle the interruption than this object does.
You shouldn't assume wait returns only when the thread is notified, it can return without a notification. That's one of the reasons to call wait in a loop.
Reworked version:
public synchronized boolean addWorkItem(Integer i) throws InterruptedException {
while (queue.size() >= QUEUE_SIZE) {
wait();
}
queue.addLast(i);
notify();
return true;
}
If you want an excuse to return false from this you could make the method return false if the queue doesn't make room for the new entry within some time frame (having a timeout can be a good thing in a lot of real-life situations):
public synchronized boolean addWorkItem(Integer i) throws InterruptedException {
final long maxWaitTime = 60L * 1000;
long totalWaitTime = 0;
while (queue.size() >= QUEUE_SIZE && totalWaitTime <= maxWaitTime) {
long waitStartTime = System.currentTimeMillis();
wait(maxWaitTime);
totalWaitTime += (System.currentTimeMillis() - waitStartTime);
}
if (queue.size() >= QUEUE_SIZE) {
return false;
}
queue.addLast(i);
notify();
return true;
}
This will still use the retry buffer (which the first version above it won't do at all), but probably not nearly as much as you are now.
Another thing: you have producer and consumer threads concurrently accessing this, and notify is called for both cases. Since notify only wakes up one thread, it's possible for a thread to get a notification that isn't relevant for it (so the notified thread wakes up, checks its condition and finds it still false, then waits some more, while another thread that the notification actually matters to never finds out about it). There are different ways to solve the problem, you can
assign separate locks, one for producers and one for consumers,
reduce the timeout passed into the wait method so you're less dependent on getting notified, or
you can use notifyAll (less performant but a quick fix).
Have a look at this.
Short story: A waiting thread can be woken up by another one calling notify. So in your case addWorkItem will return false in a thread that called wait() just after another thread calls notify().
Also having a look at your logic I think you are trying to block the consumer when the queue is empty and awake it when there is job to be done.
And you want the producer not to deliver new jobs until the queue is empty.
If this is the case, then calling return after waiting will just close your consumer/producer not letting them finish their jobs when they can.

Consumer thread does not get notified [duplicate]

I have a thread that calls the wait method and can only be awoken when the notify method called from some other class:
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
notify();
}
}
}
In the above code if the synchronized block in main, if the ThreadA does not execute first and instead the other synchronization block executing and completes to completion, then ThreadA executes its synchronized block and calls wait, what is going to happen and how it will be notified again?
If ThreadB gets through its synchronized block before ThreadA does, then ThreadA will block indefinitely on the call to wait. It won't somehow be notified that the other thread has already completed.
The problem is that you're trying to use wait and notify in ways that they are not designed to be used. Usually, wait and notify are used to have one thread wait until some condition is true, and then to have another thread signal that the condition may have become true. For example, they're often used as follows:
/* Producer */
synchronized (obj) {
/* Make resource available. */
obj.notify();
}
/* Consumer */
synchronized (obj) {
while (/* resource not available */)
obj.wait();
/* Consume the resource. */
}
The reason that the above code works is that it doesn't matter which thread runs first. If the producer thread creates a resource and no one is waiting on obj, then when the consumer runs it will enter the while loop, notice that the resource has been produced, and then skip the call to wait. It can then consume the resource. If, on the other hand, the consumer runs first, it will notice in the while loop that the resource is not yet available and will wait for some other object to notify it. The other thread can then run, produce the resource, and notify the consumer thread that the resource is available. Once the original thread is awoken, it will notice that the condition of the loop is no longer true and will consume the resource.
More generally, Java suggests that you always call wait in a loop because of spurious notifications in which a thread can wake up from a call to wait without ever being notified of anything. Using the above pattern can prevent this.
In your particular instance, if you want to ensure that ThreadB has finished running before ThreadA executes, you may want to use Thread.join(), which explicitly blocks the calling thread until some other thread executes. More generally, you may want to look into some of the other synchronization primitives provided by Java, as they often are much easier to use than wait and notify.
You could loop and wait until the total has been computed :
synchronized(b) {
while (total == 0) {
b.wait();
}
}
You could also use a higher-level abstraction like a CountDownLatch.
It is possible for ThreadB's run method to complete before you enter the synchronized block in ThreadA.main. In that situation, since the notify call has happened before you started waiting, ThreadA will block forever on the wait call.
A simple workaround would be to grab the lock on b in main before you start the second thread to ensure the wait happens first.
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
...
b.wait();
}
You probably want to use a java.util.concurrent.Semaphore for this.
1) You need to add some flag that is used to communicate between the threads, so that B can signal to A when it is finished. A simple boolean variable is fine, as long as it is only read and written within the synchronized blocks.
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
isDone = true;
notify();
}
2) A needs to loop while waiting. So if your boolean variable was called isDone, and was set to true by threadB, then threadA should have some code like this:
synchronized(b) {
System.out.println("Waiting for b to complete...");
while( ! isDone ) b.wait();
}
In this particular case, there's actually no reason to have the synchronized block in A - since threadB doesn't do anything after it finishes running, and A doesn't do anything except wait for B, threadA could simply call b.join() to block until it finishes. I assume that your actual use case is more complex than this.
Why to make that complex ? Just use join() function of Thread.
ThreadB b = new ThreadB();
b.start();
b.join();
// now print b.total
do not synchronized(thread), don't do it, do not synchronized(thread).. repat: no synchronized(thread) :)
And if you need to wait for the thread 'b' to finish, use b.join(), now your code is free to hang in b.wait()
--
Hopefully the source below can grant you an insight while sync(thread)/notify() I consider bad practice. (cut-cut)
Enjoy
To proceeed below you make sure you have accepted Oracle's License aggreement, found there:
https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewLicense-Start?LicenseUUID=7HeJ_hCwhb4AAAEtmC8ADqmR&ProductUUID=pGqJ_hCwj_AAAAEtB8oADqmS&cnum=&evsref=&sln=
Java sources (incl), called in init(), effectively called by any java c-tor, since java 1.5
private static **synchronized int** nextThreadNum() {
return threadInitNumber++;
}
//join (the method w/ nanos only increase millis by one, if nanos>500000, millis==0 and nanos>0
public final **synchronized** void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public **synchronized** void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
//stop1 is called after stop ensures proper priviledges
private final **synchronized** void stop1(Throwable th) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if ((this != Thread.currentThread()) ||
(!(th instanceof ThreadDeath))) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW"
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
stop0(th);
} else {
// Must do the null arg check that the VM would do with stop0
if (th == null) {
throw new NullPointerException();
}
// Remember this stop attempt for if/when start is used
stopBeforeStart = true;
throwableFromStop = th;
}
}

Difference between notify() and notifyAll()

I know that similar questions have been discussed in this site, but I have not still got further by their aid considering a specific example. I can grasp the difference of notify() and notifyAll() regarding Thread "awakeining" in theory but I cannot perceive how they influence the functionality of program when either of them is used instead of the other. Therefore I set the following code and I would like to know what is the impact of using each one of them. I can say from the start that they give the same output (Sum is printed 3 times).
How do they differ virtually? How could someone modify the program, in order for the applying notify or notifyAll to play a crucial role to its functionality (to give different results)?
Task:
class MyWidget implements Runnable {
private List<Integer> list;
private int sum;
public MyWidget(List<Integer> l) {
list = l;
}
public synchronized int getSum() {
return sum;
}
#Override
public void run() {
synchronized (this) {
int total = 0;
for (Integer i : list)
total += i;
sum = total;
notifyAll();
}
}
}
Thread:
public class MyClient extends Thread {
MyWidget mw;
public MyClient(MyWidget wid) {
mw = wid;
}
public void run() {
synchronized (mw) {
while (mw.getSum() == 0) {
try {
mw.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Sum calculated from Thread "
+ Thread.currentThread().getId() + " : " + mw.getSum());
}
}
public static void main(String[] args) {
Integer[] array = { 4, 6, 3, 8, 6 };
List<Integer> integers = Arrays.asList(array);
MyWidget wid = new MyWidget(integers);
Thread widThread = new Thread(wid);
Thread t1 = new MyClient(wid);
Thread t2 = new MyClient(wid);
Thread t3 = new MyClient(wid);
widThread.start();
t1.start();
t2.start();
t3.start();
}
}
UPDATE:
I write it explicitly. The result is the same whether one uses notify or notifyAll:
Sum calculated from Thread 12 : 27
Sum calculated from Thread 11 : 27
Sum calculated from Thread 10 : 27
Therefore my question: What is the difference?
The difference is subtler than your example aims to provoke. In the words of Josh Bloch (Effective Java 2nd Ed, Item 69):
... there may be cause to use notifyAll in place of notify. Just as placing the wait invocation in a loop protects against accidental or malicious notifications on a publicly accessible object, using notifyAll in place of notify protects against accidental or malicious waits by an unrelated thread. Such waits could otherwise “swallow” a critical notification, leaving its intended recipient waiting indefinitely.
So the idea is that you must consider other pieces of code entering wait on the same monitor you are waiting on, and those other threads swallowing the notification without reacting in the designed way.
Other pitfalls apply as well, which can result in thread starvation, such as that several threads may wait for different conditions, but notify always happens to wake the same thread, and the one whose condition is not satisfied.
Even though not immediately related to your question, I feel it is important to quote this conclusion as well (emphasis by original author):
In summary, using wait and notify directly is like programming in “concurrency assembly language,” as compared to the higher-level language provided by java.util.concurrent. There is seldom, if ever, a reason to use wait and notify in new code. If you maintain code that uses wait and notify, make sure that it always invokes wait from within a while loop using the standard idiom. The notifyAll method should generally be used in preference to notify. If notify is used, great care must be taken to ensure liveness.
This is made clear in all sorts of docs. The difference is that notify() selects (randomly) one thread, waiting for a given lock, and starts it. notifyAll() instead, restarts all threads waiting for the lock.
Best practice suggests that threads always wait in a loop, exited only when the condition on which they are waiting is satisfied. If all threads do that, then you can always use notifyAll(), guaranteeing that every thread whose wait condition has been satisfied, is restarted.
Edited to add hopefully enlightening code:
This program:
import java.util.concurrent.CountDownLatch;
public class NotifyExample {
static final int N_THREADS = 10;
static final char[] lock = new char[0];
static final CountDownLatch latch = new CountDownLatch(N_THREADS);
public static void main(String[] args) {
for (int i = 0; i < N_THREADS; i++) {
final int id = i;
new Thread() {
#Override public void run() {
synchronized (lock) {
System.out.println("waiting: " + id);
latch.countDown();
try { lock.wait(); }
catch (InterruptedException e) {
System.out.println("interrupted: " + id);
}
System.out.println("awake: " + id);
}
}
}.start();
}
try { latch.await(); }
catch (InterruptedException e) {
System.out.println("latch interrupted");
}
synchronized (lock) { lock.notify(); }
}
}
produced this output, in one example run:
waiting: 0
waiting: 4
waiting: 3
waiting: 6
waiting: 2
waiting: 1
waiting: 7
waiting: 5
waiting: 8
waiting: 9
awake: 0
None of the other 9 threads will ever awaken, unless there are further calls to notify.
notify wakes (any) one thread in the wait set, notifyAll wakes all threads in the waiting set. notifyAll should be used most of the time. If you are not sure which to use, then use notifyAll.
In some cases, all waiting threads can take useful action once the wait finishes. An example would be a set of threads waiting for a certain task to finish; once the task has finished, all waiting threads can continue with their business. In such a case you would use notifyAll() to wake up all waiting threads at the same time.
Another case, for example mutually exclusive locking, only one of the waiting threads can do something useful after being notified (in this case acquire the lock). In such a case, you would rather use notify(). Properly implemented, you could use notifyAll() in this situation as well, but you would unnecessarily wake threads that can't do anything anyway.
Javadocs on notify.
Javadocs on notifyAll.
Once only one thread is waiting to sum to not be zero, there is no difference. If there are several threads waiting, notify will wake up only one of them, and all the other will wait forever.
Run this test to better understand the difference:
public class NotifyTest implements Runnable {
#Override
public void run ()
{
synchronized (NotifyTest.class)
{
System.out.println ("Waiting: " + this);
try
{
NotifyTest.class.wait ();
}
catch (InterruptedException ex)
{
return;
}
System.out.println ("Notified: " + this);
}
}
public static void main (String [] args) throws Exception
{
for (int i = 0; i < 10; i++)
new Thread (new NotifyTest ()).start ();
Thread.sleep (1000L); // Let them go into wait ()
System.out.println ("Doing notify ()");
synchronized (NotifyTest.class)
{
NotifyTest.class.notify ();
}
Thread.sleep (1000L); // Let them print their messages
System.out.println ("Doing notifyAll ()");
synchronized (NotifyTest.class)
{
NotifyTest.class.notifyAll ();
}
}
}
I found what is going on with my program. The three Threads print the result even with the notify(), because they do not manage to enter the waiting state. The calculation in the widThread is performed quickly enough to preempt the entering of the other Threads in the waiting state, since it depends on the condition mw.getSum() == 0 (while loop). The widThread calculates the sum, so that the remaining Threads do not ever "see" its value as 0.
If the while loop is removed and the start of widThread comes after the start of the other Threads, then by notify() only one Thread prints the result and the others are waiting forever, as the theory and the other answers indicate.

Categories

Resources