Reputation: 13372
We have two threads, Thread2 waits for Thread1 (receiving the messages from it)
class Thread1 .. {
run() {
synchronized(this) { some-work; notify(); }
}
}
class Thread2 .. {
run() {
while(true) {
synchronized(thread1) {
...
thread1.wait();
...
println("Got here"); // has received the notify() from Thread1
}
}
}
}
After starting these threads in that sequence, we have the situation when thread2 is waiting for the notify() from thread1, and this will happen in couple of moments - the message "Got here" will be appeared.
But if I put a delay here:
class Thread2
run() {
while(true) {
sleep(1000); // the dalay
synchronized(thread1) { ..
}
Then the message 'Got Here' will be never appeared - because thread2 will miss the notify() from thread1 before the sycnronized(thread1) is reached - then we have a situation when Nothing To Wait.
The question is:
1. Are these two lines atomic. Or better say is this gap between these two lines atomic?:
while(true) {
// gap
synchronized(thread1) {..thread.wait() ..}
}
2. Or does it mean that we should not put any expression between while() and synchronized block? For example, we could have:
while(true) {
int a = 0; a++;
synchronized(thread1) {..thread.wait() ..}
Because it we have those expressions there then we have a risk of 'nothing-to-wait' situation?
Upvotes: 0
Views: 638
Reputation: 451
wait
and notify
are not sufficient to create a signalling mechanism, for the reason that you've discovered: if you don't have any waiters, then the notify goes into the bit bucket.
A Semaphore is sufficient: if the sender returns the permit while the receiver is doing something else, then the receiver will immediately get that permit.
But, as some commenters said, a BlockingQueue is a better solution, as it means your code doesn't have to know anything about threading.
Upvotes: 2
Reputation: 8163
Actually, you ask whether this could happen without the sleep(), right? Imho the answer is yes. While the "gap" is just that - nothing - the loop itself consists of actual instructions as well. In between them, the threads can get switched. IMHO it is also not garantueed that you reach Thread2.run before Thread1.run just because you started Thread2 first. I'm not sure how to solve this problem, though. Maybe have Thread1 wait for Thread2 somehow?
Upvotes: 1
Reputation:
No gap between lines is "atomic", the concept of atomicity does not apply here.
If you want to avoid missing the notify, start thread1 in the body of thread2's run method.
Upvotes: 1