ses
ses

Reputation: 13372

Java Multi-threading and atomic gap between while() and synchronized block that waits

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   
    }
   }
 }

}

  1. thread2.start() // thred2 is first to be ready to receive all messages from thread1
  2. thread1.start()

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

Answers (3)

parsifal
parsifal

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

kutschkem
kutschkem

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

user570500
user570500

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

Related Questions