2

I'm using a ReentrantLock along with a Condition to synchronise two threads. Whenever the consumer threads performs an await() on the condition before the producer thread performs a signal(), things seem to work fine. However, when the producer thread performs a signal() before the consumer thread performs an await(), then the consumer thread just ends up waiting for ever. Is this supposed to happen or am I doing something wrong? What is the expected behaviour when a condition is signalled and there are no waiting threads?

Here's the code for the consumer:

this.lock.lock();
Log.d("websocket", "Sender acquired lock");
try
{
    Log.d("websocket", "Sender waiting for message from server");
    this.resultReady.await();
    Log.d("websocket", "Sender waking up");
    return this.result;

} catch (InterruptedException e)
{
    e.printStackTrace();
}
finally {
    this.lock.unlock();
}

Here's the code for the producer:

Log.d("websocket", "Receiver acquiring lock");
this.lock.lock();
Log.d("websocket", "Receiver acquired lock");
try
{
    Log.d("websocket", "Receiver setting result");
    result = serviceResult;
    Log.d("websocket", "Receiver waking up waiting threads");
    this.resultReady.signal();
} finally
{
    this.lock.unlock();
}
faridghar
  • 1,445
  • 2
  • 13
  • 25
  • I don't see what you are producing or consuming? Needs more code. I just did a problem like this and the trick for the consumer is to test for the item(s) to be available first, then wait only if the buffer is empty. With no items here to look for, I don't know what you are really trying to do. – markspace Aug 09 '14 at 15:06
  • I don't have a buffer in this scenario. I just have a piece of data (`result`) which is set by my producer when a message is received from a socket. I need my consumer to be notified when the message is received. My problem isn't that the consumer is waiting despite the buffer not being empty. My problem is that when the producer sets the data **before** the consumer has began waiting for it, the consumer ends up waiting for ever when he eventually calls `await()`. However, when the producer sets the data (calls `signal()`) **after** the consumer has called `await()` everything works fine. – faridghar Aug 09 '14 at 15:18
  • Just to be clear, the explicit question is: Is it possible to signal() a Condition when no threads are waiting on it. If so, when a thread eventually does come and wait, does it just go right through? – faridghar Aug 09 '14 at 15:56

1 Answers1

3

Is this supposed to happen or am I doing something wrong? What is the expected behaviour when a condition is signalled and there are no waiting threads?

That's supposed to happen. There's no effect if there's no threads waiting. The Java doc says:

Wakes up one waiting thread.

If any threads are waiting on this condition then one is selected for waking up. That thread must then re-acquire the lock before returning from await.

Surely if there's no threads to wake up, then there is no effect?

You have a buffer, which contains one item, your result. You must test this result to be valid independently of the await() method. Or switch to something like a Semaphore which does have an internal state you can set.

// Consumer
this.lock.lock();
Log.d("websocket", "Sender acquired lock");
try
{
    Log.d("websocket", "Sender waiting for message from server");
    while( result == null )   // CHANGE HERE
        resultReady.await();
    Log.d("websocket", "Sender waking up");
    return this.result;

} catch (InterruptedException e)
{
    e.printStackTrace();
}
finally {
    this.lock.unlock();
}
markspace
  • 10,621
  • 3
  • 25
  • 39
  • Excellent, thanks! My secondary problem is that the test `result == null` won't really work for me because I'll have no way of knowing if the result is "fresh" or if it's still hanging around from before. But that's a separate issue all together which I can probably solve by having an array as a buffer instead of just a single variable. Thanks again. – faridghar Aug 09 '14 at 16:30