Condition vs wait notify mechanism - java

What is the advantage of using Condition interface/implementations over the conventional wait notify mechanism? Here I quote the comments written by Doug Lea:
Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
I see this is a more Object Oriented way of implementing wait/notify mechanism. But is there a sound advantage over the former?

The biggest problem is that wait/notify is error prone for new developers. The main problem is not knowing how to handle them correctly can result is obscure bug.
if you call notify() before wait() it is lost.
it can be sometimes unclear if notify() and wait() are called on the same object.
There is nothing in wait/notify which requires a state change, yet this is required in most cases.
wait() can return spuriously
Condition wraps up this functionality into a dedicated component, however it behaves much the same.
There is a question regarding wait/nofity posted minutes before this one and many, many more Search [java]+wait+notify

When you use Condition: await()/signal() you can distinguish which object or group of objects/threads get a specific signal. Here is a short example where some threads, the producers, will get the isEmpty signal while the consumers will get the isFull signal:
private volatile boolean usedData = true;//mutex for data
private final Lock lock = new ReentrantLock();
private final Condition isEmpty = lock.newCondition();
private final Condition isFull = lock.newCondition();
public void setData(int data) throws InterruptedException {
lock.lock();
try {
while(!usedData) {//wait for data to be used
isEmpty.await();
}
this.data = data;
isFull.signal();//broadcast that the data is now full.
usedData = false;//tell others I created new data.
}finally {
lock.unlock();//interrupt or not, release lock
}
}
public void getData() throws InterruptedException{
lock.lock();
try {
while(usedData) {//usedData is lingo for empty
isFull.await();
}
isEmpty.signal();//tell the producers to produce some more.
usedData = true;//tell others I have used the data.
}finally {//interrupted or not, always release lock
lock.unlock();
}
}

There are many advantages like mentioned above about Condition Interface some important are as follows:
Condition interface comes with Two extra methods that are:
1)boolean awaitUntil(Date deadline)throws InterruptedException :
Causes the current thread to wait until it is signalled or interrupted, or the specified deadline elapses.
2)awaitUninterruptibly() :
Causes the current thread to wait until it is signalled.
If the current thread's interrupted status is set when it enters this method, or it is interrupted while waiting, it will continue to wait until signalled. When it finally returns from this method its interrupted status will still be set.
The above two methods are not present in default monitor that is in object class,in some situations we want to set the deadline for thread to wait then we are able to do that by Condition interface.
In some situations we don't want thread to be interrupted and want current thread to wait until it is signaled then we can go for awaitUninterruptibly method present in Condition Interface.
For more information Condition Interface Java Documentation:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html#awaitUntil%28java.util.Date%29

To specifically address why having multiple waitsets is an advantage:
With wait/notify if there are different things that threads are waiting for (the common example is a fixed size blocking queue, with some threads putting things in the queue and blocking when the queue is full, and other threads taking from the queue and blocking when the queue is empty) then if you use notify, causing the scheduler to pick one thread from the wait set to notify, you can have corner cases where the chosen thread isn't interested in being notified for a particular situation. For instance the queue will notify for adding something to the queue, but if the chosen thread is a producer and the queue is full then it can't act on that notification, which you would rather have gone to a consumer. With intrinsic locking you have to use notifyAll in order to make sure that notifications don't get lost.
But notifyAll incurs churn with every call, where every thread wakes up and contends for the lock, but only one can make progress. The other threads all bump around contending for the lock until, one at a time, they can acquire the lock and most likely go back to waiting. It generates a lot of contention for not much benefit, it would be preferable to be able to use notify and know only one thread is notified, where the notification is relevant to that thread.
This is where having separate Conditions to wait on is a big improvement. The queue can invoke signal on a condition and know it will wake up only one thread, where that thread is specifically waiting for the condition.
The API doc for Condition has a code example that shows using multiple conditions for a bounded buffer, it says:
We would like to keep waiting put threads and take threads in separate wait-sets so that we can use the optimization of only notifying a single thread at a time when items or spaces become available in the buffer.

In addition to other well accepted answers - since Condition is associated with Lock object you can have arbitrary sets of Lock objects (reawrite, read, write) in your class and have specific condition associated with that. Then you can use those set of condition to synchronize different parts of your class according to your implementation semantics. This gives more flexibility and explicit behavior then wait-notify imo

Related

What does it mean by waiting on object monitor [duplicate]

Someone at work just asked for the reasoning behind having to wrap a wait inside a synchronized.
Honestly I can't see the reasoning. I understand what the javadocs say--that the thread needs to be the owner of the object's monitor, but why? What problems does it prevent? (And if it's actually necessary, why can't the wait method get the monitor itself?)
I'm looking for a fairly in-depth why or maybe a reference to an article. I couldn't find one in a quick google.
Oh, also, how does thread.sleep compare?
edit: Great set of answers--I really wish I could select more than one because they all helped me understand what was going on.
Lots of good answers here already. But just want to mention here that the other MUST DO when using wait() is to do it in a loop dependent on the condition you are waiting for in case you are seeing spurious wakeups, which in my experience do happen.
To wait for some other thread to change a condition to true and notify:
synchronized(o) {
while(! checkCondition()) {
o.wait();
}
}
Of course, these days, I'd recommend just using the new Condition object as it is clearer and has more features (like allowing multiple conditions per lock, being able to check wait queue length, more flexible schedule/interrupt, etc).
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (! checkCondition()) {
condition.await();
}
} finally {
lock.unlock();
}
}
If the object does not own the object monitor when it calls Object.wait(), it will not be able to access the object to setup a notify listener until the the monitor is released. Instead, it will be treated as a thread attempting to access a method on a synchronized object.
Or to put it another way, there is no difference between:
public void doStuffOnThisObject()
and the following method:
public void wait()
Both methods will be blocked until the object monitor is released. This is a feature in Java to prevent the state of an object from being updated by more than one thread. It simply has unintended consequences on the wait() method.
Presumably, the wait() method is not synchronized because that could create situations where the Thread has multiple locks on the object. (See Java Language Specifications/Locking for more info on this.) Multiple locks are a problem because the wait() method will only undo one lock. If the method were synchronized, it would guarantee that only the method's lock would be undone while still leaving a potential outer lock undone. This would create a deadlock condition in the code.
To answer your question on Thread.sleep(), Thread.sleep() does not guarantee that whatever condition you are waiting on has been met. Using Object.wait() and Object.notify() allows a programmer to manually implement blocking. The threads will unblock once a notify is sent that a condition has been met. e.g. A read from disk has finished and data can be processed by the thread. Thread.sleep() would require the programmer to poll if the condition has been met, then fall back to sleep if it has not.
It needs to own the monitor, since the purpose of the wait() is to release the monitor and let other threads obtain the monitor to do processing of their own. The purpose of these methods (wait/notify) is to coordinate access to synchronized code blocks between two threads that require each other to perform some functionality. It is not simply a matter of making sure access to a data structure is threadsafe, but to coordinate events between multiple threads.
A classic example would be a producer/consumer case where one thread pushes data to a queue, and another thread consumes the data. The consuming thread would always require the monitor to access the queue, but would release the monitor once the queue is empty. The producer thread would then only get access to write to the thread when the consumer is no longer processing. It would notify the consumer thread once it has pushed more data into the queue, so it can regain the monitor and access the queue again.
Wait gives up the monitor, so you must have it to give it up. Notify must have the monitor as well.
The main reason why you want to do this is to ensure that you have the monitor when you come back from wait() -- typically, you are using the wait/notify protocol to protect some shared resource and you want it to be safe to touch it when wait returns. The same with notify -- usually you are changing something and then calling notify() -- you want to have the monitor, make changes, and call notify().
If you made a function like this:
public void synchWait() {
syncronized { wait(); }
}
You would not have the monitor when wait returned -- you could get it, but you might not get it next.
Here's my understanding on why the restriction is actually a requirement. I'm basing this on a C++ monitor implementation I made a while back by combining a mutex and a condition variable.
In a mutex+condition_variable=monitor system, the wait call sets the condition variable into a wait state and releases the mutex. The condition variable is shared state, so it needs to be locked to avoid race conditions between threads that want to wait and threads that want to notify. Instead of introducing yet another mutex to lock its state, the existing mutex is used. In Java, the mutex is correctly locked when the about-to-wait thread owns the monitor.
Mostly wait is done if there is a condition say a queue is empty.
If(queue is empty)
queue.wait();
Let us assume the queue is empty.
In case if the current thread pre-empts after checking the queue, then if another
thread adds few elements to queue, the current thread will not know and will go for wait
state. Thats wrong.
So we should have something like
Synchornized(queue)
{
if(queue is empty)
queue.wait();
}
Now let us consider what if they made wait itself as synchronized. As already mentioned in one of the comments, it releases only one lock. That means if wait() was synchronized in the above code only one lock would have been released. Implies that current thread will go for wait with the lock for the queue.

Access to shared resource, lock unlock or wait notify

Scenario:
Multi-threads reading from different sources.
One single access point to a shared queue (See a class RiderSynchronized trying to write)
Every line a Reader reads, It tries to insert into a shared queue through method RiderSynchronized provides.
When shared queue is full, I have to run a batch on a prepared statement to insert into Oracle. Meanwhile, all access to shared queue it must be denied.
Code:
public class RiderSynchronized {
private ArrayDeque<JSONRecord> queue = new ArrayDeque<>();
private OracleDAO oracleDao;
private long capacity;
public RiderSynchronized(OracleDAO oracleDao, long capacity) {
this.oracleDao = oracleDao;
this.capacity = capacity;
}
public synchronized boolean addRecord(JSONRecord record) {
boolean success = false;
try {
while (queue.size() >= capacity) {
wait();
}
queue.add(record);
if (queue.size() < capacity) {
success = true;
notify(); //notify single Thread
} else {
JSONRecord currentRecord = null;
while ((currentRecord = queue.poll()) != null) {
oracleDao.insertRowParsedIntoBatch(currentRecord);
}
oracleDao.runBatch();
success = true;
notifyAll(); //it could be all Reading Threads are waiting. Notify all
}
} catch (Exception e) {
success = false;
}
return success;
}
}
I have to admit I'm a little worried about a thing.
1) Reader threads can just use addRecord indistinctly? Are They going to wait for themselves? Or Do I have to implement some other method where to check before to run addRecord Method?
2) When queue.size < capacity, I decide to notify just to one thread, because IMHO, at this point, no threads should be in status waiting. Am I wrong? Should I notify All?
2b) Exact question for the "else" statement. Is it a good practice to notifyAll? At this point, it could be all threds are waiting?
3) Finally. I'm a little concerned to re-write everything using Lock e Condition Classes. Is it a better decision? Or Is it ok how I'm running this scenario?
1) Reader threads can just use addRecord indistinctly? Are They going
to wait for themselves? Or Do I have to implement some other method
where to check before to run addRecord Method?
The problem with your current code is that if for some reason notifyAll is not called by the only thread that theoretically should be able to go into the else block then your threads will wait forever.
The potential risks in your code are:
oracleDao.insertRowParsedIntoBatch(currentRecord)
oracleDao.runBatch()
With your current code if one of those methods throw an exception notifyAll will never be called so your threads will wait forever, you should at least consider calling notifyAll in a finally block to make sure that it will be called whether happens.
2) When queue.size < capacity, I decide to notify just to one thread,
because IMHO, at this point, no threads should be in status waiting.
Am I wrong? Should I notify All?
Your threads could only wait in case queue.size() >= capacity so for me notify is not even needed as this condition (queue.size() < capacity) is not expected by any thread.
2b) Exact question for the "else" statement. Is it a good practice to
notifyAll? At this point, it could be all threds are waiting?
Item 69 from Effective Java:
A related issue is whether you should use notify or notifyAll to wake
waiting threads. (Recall that notify wakes a single waiting thread,
assuming such a thread exists, and notifyAll wakes all waiting
threads.) It is often said that you should always use notifyAll. This
is reasonable, conservative advice. It will always yield correct
results because it guarantees that you’ll wake the threads that need
to be awakened. You may wake some other threads, too, but this won’t
affect the correctness of your program. These threads will check the
condition for which they’re waiting and, finding it false, will
continue waiting. As an optimization, you may choose to invoke notify
instead of notifyAll if all threads that could be in the wait-set are
waiting for the same condition and only one thread at a time can
benefit from the condition becoming true. Even if these conditions
appear true, 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.
3) Finally. I'm a little concerned to re-write everything using Lock e
Condition Classes. Is it a better decision? Or Is it ok how I'm
running this scenario?
Lock and Condition are interesting if you need features that are not available with intrinsic locks like for example tryLock() or the ability to awake only threads waiting for a given condition. In your case it doesn't seem to be necessary so you can keep it like it is.
I'll try to answer you question one by one.
1) If I understand you correctly answer is yes thread will wait and you don't need to do anything else.
2) You don't need to notify anyone in case of queue.size < capacity there are no waiting thread at this point.
3) Yes it is ok to notify all. If more threads than capacity is waiting rest of them come to wait state fast.
4) It is opinion based question. In your scenario you wont get any benefit from rewriting.

while(condition) { Object.wait() } idiom

I know, that we use this idiom for waiting for notification to handle spurious wakeups:
synchronized (obj) {
while(somecond)
obj.wait();
}
If a spurious wake up arises, we'll just check the state and return back to waiting.
But, consider the situation:
We begin waiting, and obj.wait() releases lock on obj.
Waiting thread is spuriously notified by OS
We return to checking condition (with obj lock released due to wait)
obj.notify() is called right in that moment.
Yes, condition checking is extremely fast and chances, that we can be in condition checking and not in obj.wait(), are negligibly small. In that case we can loose obj.notify() call.
Am I misunderstanding something, or we really can loose notification using this pattern?
Another thread needs the lock on obj to be able to call obj.notify(). And it can't have it if your thread is in the while loop not waiting, since your thread also needs the lock on obj to be in the while loop.
The call to obj.wait() will not return until an obj.notify() has been called. However, you might fail to respond to an obj.notify() if another thread is also waiting and the system decides to notify that thread instead. If you want to avoid that, you can use obj.notifyAll(). If only one thread is waiting, you cannot lose the notification with this pattern.
Note that the other thread cannot call obj.notify() unless it holds the lock. If this thread is busy checking the condition, then it has the lock and the other thread cannot issue a notification. The synchronized block is essential to the operation.
In the case you present, Thread A is evaluating the condition, and Thread B is calling notify such that Thread A misses the notify call
This scenario would not be possible for that notify to be called since it must own the lock that Thread A is using in the synchronized block - only one thread can own that lock at once. See the javadoc on notify for more details.
The modifications to the state we are checking should be made, while the lock on obj is held by whomever calls obj.notify() afterwards. So, assuming we are currently checking the state, we are also holding the lock on obj.
If we are getting a spurious wake up, and the state has not changed, no one should have called obj.notify(). If the state has changed and we we miss a obj.notify(), it does not matter: For all intends, a spurious wake up and a wakeup by a call to obj.notifiy() have the same effect now.
The lesson is, that the state we are checking for should only be changed, while whoever is changing the state holds a lock on the object we are waiting on.
Since most of the answers insist on the impossibility of the scenario it’s worth to adjust that:
It is always possible to have a call to notify without a matching waiting thread. This might happen when the notifying thread invokes notify before the other thread even entered the entire synchronized block. The notify method might even have been called multiple times before any thread enters a synchronized block to wait and the wait-notify mechanism won’t count these.
So you have to handle the case that you missed a notify, e.g. by checking the condition within the synchronized block before calling wait. But by doing so you add the possibility to process and reset the condition while the matching notify is indeed pending.
Therefore you must be always aware of the possibilities that either
you may have missed one or more notify invocations
you may receive an obsolete notify
That’s why the correct handling loop likes like that
synchronized(obj) {
while(somecond)
obj.wait();
}
From an application’s point of view there is no difference between outdated pending notifys and the spurious wakeups generated by the JVM/OS without associated notify invocations. That’s why there is no attempt to prevent spurious wakeups by the JVM. The effort would be wasted as the logic wouldn’t change.

Why should wait() always be called inside a loop

I have read that we should always call a wait() from within a loop:
while (!condition) { obj.wait(); }
It works fine without a loop so why is that?
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
For example, you are waiting for something:
synchronized (theObjectYouAreWaitingOn) {
while (!carryOn) {
theObjectYouAreWaitingOn.wait();
}
}
An evil thread comes along and:
theObjectYouAreWaitingOn.notifyAll();
If the evil thread does not/can not mess with the carryOn you just continue to wait for the proper client.
Edit: Added some more samples.
The wait can be interrupted. It throws InterruptedException and you might need to wrap the wait in a try-catch. Depending on your business needs, you can exit or suppress the exception and continue waiting.
It's answered in documentation for Object.wait(long milis)
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(For more information on this topic,
see Section 3.2.3 in Doug Lea's
"Concurrent Programming in Java
(Second Edition)" (Addison-Wesley,
2000), or Item 50 in Joshua Bloch's
"Effective Java Programming Language
Guide" (Addison-Wesley, 2001).
Why should wait() always be called inside a loop
The primary reason why while loops are so important is race conditions between threads. Certainly spurious wakeups are real and for certain architectures they are common, but race conditions are a much more likely reason for the while loop.
For example:
synchronized (queue) {
// this needs to be while
while (queue.isEmpty()) {
queue.wait();
}
queue.remove();
}
With the above code, there may be 2 consumer threads. When the producer locks the queue to add to it, consumer #1 may be blocked at the synchronized lock while consumer #2 is waiting on the queue. When the item is added to the queue and notify called by the producer, #2 is moved from the wait queue to be blocked on the queue lock, but it will be behind the #1 consumer which was already blocked on the lock. This means that the #1 consumer gets to go forward first to call remove() from the queue. If the while loop is just an if, then when consumer #2 gets the lock after #1 and calls remove(), an exception would occur because the queue is now empty -- the other consumer thread already removed the item. Even though it was notified, it needs to be make sure the queue is for sure not empty because of this race condition.
This well documented. Here's a web page I created a while back which explains the race condition in detail and has some sample code.
There might be more then just one worker waiting for a condition to become true.
If two or more worker get awake (notifyAll) they have to check the condition again.
otherwise all workers would continue even though there might only be data for one of them.
I think I got #Gray 's answer.
Let me try to rephrase that for newbies like me and request the experts to correct me if I am wrong.
Consumer synchronized block::
synchronized (queue) {
// this needs to be while
while (queue.isEmpty()) {
queue.wait();
}
queue.remove();
}
Producer synchronized block::
synchronized(queue) {
// producer produces inside the queue
queue.notify();
}
Assume the following happens in the given order:
1) consumer#2 gets inside the consumer synchronized block and is waiting since queue is empty.
2) Now, producer obtains the lock on queueand inserts inside the queue and calls notify().
Now,either consumer#1 can be chosen to run which is waiting for queue lock to enter the synchronized block for the first time
or
consumer#2 can be chosen to run.
3) say, consumer#1 is chosen to continue with the execution. When it checks the condition,it will be true and it will remove() from the queue.
4) say,consumer#2 is proceeding from where it halted its execution (the line after the wait() method). If 'while' condition is not there (instead an if condition), it will just proceed to call remove() which might result in an exception/unexpected behaviour.
Because wait and notify are used to implement [condition variables](http://en.wikipedia.org/wiki/Monitor_(synchronization)#Blocking_condition_variables) and so you need to check whether the specific predicate you're waiting on is true before continuing.
Both safety and liveness are concerns when using the wait/notify mechanism. The safety property requires that all objects maintain consistent states in a multithreaded environment. The liveness property requires that every operation or method invocation execute to completion without interruption.
To guarantee liveness, programs must test the while loop condition before invoking the wait() method. This early test checks whether another thread has already satisfied the condition predicate and sent a notification. Invoking the wait() method after the notification has been sent results in indefinite blocking.
To guarantee safety, programs must test the while loop condition after returning from the wait() method. Although wait() is intended to block indefinitely until a notification is received, it still must be encased within a loop to prevent the following vulnerabilities:
Thread in the middle: A third thread can acquire the lock on the shared object during the interval between a notification being sent and the receiving thread resuming execution. This third thread can change the state of the object, leaving it inconsistent. This is a time-of-check, time-of-use (TOCTOU) race condition.
Malicious notification: A random or malicious notification can be received when the condition predicate is false. Such a notification would cancel the wait() method.
Misdelivered notification: The order in which threads execute after receipt of a notifyAll() signal is unspecified. Consequently, an unrelated thread could start executing and discover that its condition predicate is satisfied. Consequently, it could resume execution despite being required to remain dormant.
Spurious wakeups: Certain Java Virtual Machine (JVM) implementations are vulnerable to spurious wakeups that result in waiting threads waking up even without a notification.
For these reasons, programs must check the condition predicate after the wait() method returns. A while loop is the best choice for checking the condition predicate both before and after invoking wait().
Similarly, the await() method of the Condition interface also must be invoked inside a loop. According to the Java API, Interface Condition
When waiting upon a Condition, a "spurious wakeup" is permitted to
occur, in general, as a concession to the underlying platform
semantics. This has little practical impact on most application
programs as a Condition should always be waited upon in a loop,
testing the state predicate that is being waited for. An
implementation is free to remove the possibility of spurious wakeups
but it is recommended that applications programmers always assume that
they can occur and so always wait in a loop.
New code should use the java.util.concurrent.locks concurrency utilities in place of the wait/notify mechanism. However, legacy code that complies with the other requirements of this rule is permitted to depend on the wait/notify mechanism.
Noncompliant Code Example
This noncompliant code example invokes the wait() method inside a traditional if block and fails to check the postcondition after the notification is received. If the notification were accidental or malicious, the thread could wake up prematurely.
synchronized (object) {
if (<condition does not hold>) {
object.wait();
}
// Proceed when condition holds
}
Compliant Solution
This compliant solution calls the wait() method from within a while loop to check the condition both before and after the call to wait():
synchronized (object) {
while (<condition does not hold>) {
object.wait();
}
// Proceed when condition holds
}
Invocations of the java.util.concurrent.locks.Condition.await() method also must be enclosed in a similar loop.
Before getting to the answer, lets see how wait is probably implemented.
wait(mutex) {
// automatically release mutex
// and go on wait queue
// ... wait ... wait ... wait ...
// remove from queue
// re-acquire mutex
// exit the wait operation
}
In your example mutex is the obj with the assumption that your code is running inside synchronized(obj) { } block.
A mutex is called as monitor in Java [some subtle differences though]
A concurrency example using condition variable with if
synchronized(obj) {
if (!condition) {
obj.wait();
}
// Do some stuff related to condition
condition = false;
}
Lets say we have 2 threads. Thread 1 and Thread 2.
Lets see some states along the timeline.
at t = x
Thread 1 state:
waiting on ... wait ... wait ... wait ..
Thread 2 state:
Just entered the synchronised section, since as per the thread 1's state, the mutex/monitor is released.
You can read more about wait() here java.sun.com/javase/6/docs/api/java/lang/Object.html#wait(long).
This is the only thing that is tricky to understand. When 1 thread is inside the synchronized block. Another thread can still enter the synchronized block because wait() causes the monitor/mutex to be released.
Thread 2 is about to read if (!condition) statement.
at t = x + 1
notify() is triggered by some thread on this mutex/monitor.
condition becomes true
Thread 1 state:
Waiting at re-acquire mutex, [Since thread-2 has the lock now]
Thread 2 state:
Doesn't go inside if condition and marks the condition = false.
at t = x + 2
Thread 1 state:
Exits the wait operation and about to mark condition = false.
This state is inconsistent as condition is supposed to be true but is false already, because thread 2 marked it false previously.
And thats the reason, while is required instead of if. As while would trigger the condition to be checked again for thread 1 and thread 1 will begin waiting again.
Result
In order to avoid this inconsistency the correct code seems to be like this:
synchronized(obj) {
while (!condition) {
obj.wait();
}
// Do some stuff related to condition
condition = false;
}
From your Question:
I have read that we should always called a wait() from within a loop:
Although wait( ) normally waits until notify( ) or notifyAll( ) is called, there is a possibility that in very rare cases the waiting thread could be awakened due to a spurious wakeup. In this case, a waiting thread resumes without notify( ) or notifyAll( ) having been called.
In essence, the thread resumes for no apparent reason.
Because of this remote possibility, Oracle recommends that calls to wait( ) should take place within a loop that checks the condition on which the thread is waiting.
Three things you will see people do:
Using wait without checking anything (BROKEN)
Using wait with a condition, using an if check first (BROKEN).
Using wait in a loop, where the loop test checks the condition (NOT BROKEN).
Not appreciating these details about how wait and notify work leads people to choose the wrong approach:
One is that a thread doesn't remember notifications that happened before it got around to waiting. The notify and notifyAll methods only effect threads that are already waiting, if a thread isn't waiting at the time it is out of luck.
Another is that a thread releases the lock once it starts waiting. Once it gets a notification it re-acquires the lock and continues on where it left off. Releasing the lock means that thread does not know anything about the current state once it wakes back up, any number of other threads could have made changes since then. The check made before the thread started waiting doesn't tell you anything about what the state is currently.
So the first case, with no checking, makes your code vulnerable to race conditions. It might happen to work by accident if one thread has enough of a head start over another. Or you may have threads waiting forever. If you sprinkle in timeouts then you end up with slow code that sometimes doesn't do what you want.
Adding a condition to check apart from the notification itself protects your code from these race conditions and gives your code a way to know what the state is even if the thread wasn't waiting at the right time.
The second case, with if-checks, is likely to work if you have only 2 threads. That puts a limit on the number of states things can get into and when you made faulty assumptions you don't get burned so badly. This is the situation for lots of toy example code exercises. The result is people come away thinking they understand, when they really don't.
Protip: Real world code has more than two threads.
Using the loop lets you re-check the condition once you re-acquire the lock so that you're moving forward based on current state, not on stale state.
In simple words,
'if' is a conditional statement , once condition is satisfied remaining block of code will get executed.
'while' is a loop which going check the condition unless condition is not satisfied.

Writing a one-at-a-time lock in Java

I'm trying to implement a Java lock-type-thing which does the following:
By default, threads do not pass the lock. (Opposite from normal locks, where locks can be acquired as long as they are not held.)
If only one thread is waiting for the lock, execution in that thread stops
If more than one thread is waiting for the lock, the thread that has been waiting the longest is allowed to continue execution.
I'm working on implementing this on top of AbstractQueuedSynchronizer. The transition to allow the oldest thread to go through looks like this:
//inner class inside Lock
private static class Sync extends AbstractQueuedSynchronizer {
public Sync(){
setState(-1);
}
public boolean tryAcquire(int ignore) {
if (getState() == 1) return false;
Thread first = getFirstQueuedThread();
if (first != null &&
first != Thread.currentThread()) {
setState(0);
return false;
}
return compareAndSetState(0, 1);
The problem that I'm seeing is that when I call setState(0) but return false, the Sync object never has the first thread tryAcquire again. Do I need to use SharedMode? Is there a better solution to this problem?
This is part of an implementation of what I call a "Valve" which I want to use for long-polling AJAX responses. I've got the part where a thread waits for the valve to become "pressurized" -- there's data to send to the client) but getting the oldest thread to release seems hard unless I don't use AbstractQueuedSynchronizer, and I really don't want to write a ground-up lock implementation.
Have a look at the ReentrantLock class (http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html).
You could keep this lock object as a private variable in your class and use it to do whatever you need to do. I'm not quite sure how you could implement this without more knowledge of your code, but this Lock object has all of the methods you require to provide the behavior you mentioned in your post.
To keep track of how long a thread has been waiting, you might have to hack something together to keep track of it. I don't think the Thread class provides that kind of functionality.
Have you looked at this link
A Fair Lock
Below is shown the previous Lock class turned into a fair lock called FairLock. You will notice that the implementation has changed a bit with respect to synchronization and wait() / notify() compared to the Lock class shown earlier.
Exactly how I arrived at this design beginning from the previous Lock class is a longer story involving several incremental design steps, each fixing the problem of the previous step: Nested Monitor Lockout, Slipped Conditions, and Missed Signals. That discussion is left out of this text to keep the text short, but each of the steps are discussed in the appropriate texts on the topic ( see the links above). What is important is, that every thread calling lock() is now queued, and only the first thread in the queue is allowed to lock the FairLock instance, if it is unlocked. All other threads are parked waiting until they reach the top of the queue.

Categories

Resources