Reputation: 13998
public class MyLockConditionTest {
private final Lock alock = new ReentrantLock();
private final Condition condition = alock.newCondition();
private String message = null;
public void waitForCallback() {
alock.lock();
try {
// wait for callback from a remote server
condition.await();
doSomething(message);
} finally {
alock.unlock();
}
}
// another thread will call this method as a callback to wake up the thread called condition.await()
public void onCallbackReceived(String message) {
alock.lock();
try {
this.message = message
condition.signal();
} finally {
alock.unlock();
}
}
}
I have this code using ReentrantLock and Condition to implement a class to wait on certain callbacks from a remote server. I tested this code and seems working but I have a few questions.
Why do I need to do alock.lock() / unlock() in onCallbackReceived(). Without calling lock() / unlock(), I was getting an IllegalState exception. I am confused because the lock is held by the caller of waitForCallback() when onCallbackReceived() invoked by another thread so alock.lock() in onCallbackReceived() will always fail.
Do I need to wrap condition.await() in waitForCallback() with while loop?
while(message==null) condition.await();
Upvotes: 2
Views: 522
Reputation: 40256
Why do I need to do alock.lock() / unlock() in onCallbackReceived(). Without calling lock() / unlock(), I was getting an IllegalState exception.
You are trying to signal
a condition in which you do not own the lock. The only way you would hold the lock is if onCallbackReceived
is called from doSomething
which there is no indication that is occurring.
Do I need to wrap condition.await() in waitForCallback() with while loop?
Yes, imagine you have 5 threads stopped on the condition and 5 threads blocked on lock
. Only one thread can wake up. What if when a waiting thread finally wakes up another thread had null'd that field out? You will need to check again to ensure the predicate is still true.
Upvotes: 1