Here's a snippet of code that I saw in some code I'm maintaining.
Object lock = new Object();
synchronized( lock )
{
try
{
lock.wait( 50000 );
Thread.sleep( 3000 );
}
catch(Exception ex)
{
}
}
The developer wants to suspend the current thread for some amount of time and is using Object#wait as the mechanism. Obviously it is bad form to use the wait/notify protocol for this reason; however, is there any major difference between calling wait(millisec) and a Thread.sleep ?
Aside from having to get a monitor before waiting() there's no major difference anymore so long as no one external is going to be .notify()ing.
In ancient Java code you'd see people using wait() instead of Thread.sleep() because Thread.sleep() would freeze the whole application on systems without preemptive multitasking (I'm looking at you OS9). Technically wait() also let's you use nano-resolution waits, but in practice they're seldom that accurate.
Note that there is one key difference in using Object.wait() and Thread.sleep() inside a synchronization block: Thread.sleep() does not release the locked monitor, so no-one else can become the owner of the monitor.
In addition, Object.wait() does not guarantee that the delay indicated will be obeyed strictly. First of all, after the delay passes, the thread may still be waiting for another thread that has become the monitor owner in the meantime; and it may compete with other threads waiting to grab the monitor.
Second, the mythical spurious wake-up, as it is described in the Java 6 API javadoc:
A thread can also wake up without
being notified, interrupted, or timing
out, a so-called spurious wakeup.
Unlikely as it is, every piece of code using Object.wait() should take it into consideration.
You say it's "obviously" bad form to use wait/notify for this, but I don't see anything wrong with it. Admittedly following it up with a sleep call is very odd (and swallowing exceptions is bad), but I've definitely used Object.wait as a "breakable sleep" before now.
Imagine you've got a thread polling a resource every minute, but you want to be woken if something's happened (e.g. the resource location has changed, or the timer frequency has changed, or the program wants to quit in a graceful manner). Using wait/notify works extremely well for that - it's definitely cleaner than calling interrupt on the thread from elsewhere, as it doesn't matter if the notify occurs while you're actually processing instead of waiting.
Related
In Java, a thread can go to sleep so that it won't hog the process and other thread can get chance to run. This is done by calling sleep().
However, different from calling wait(), the thread, after calling sleep(), will NOT release the lock it's been holding. Since this thread is still holding the lock, how can other thread get chance to run while not being able to get the unreleased lock?
They can't; other threads that need to acquire a lock held by a sleeping thread will block until they can get it. There's no way to back off like tryacquire on explicit Locks, so the threads are stuck.
Threads shouldn't sleep while holding a lock. If a thread isn't doing something useful it doesn't need to be holding a lock.
To go dormant and release a lock use the wait method. Sleep doesn't have any means to cut its sleep time short other than interruption (which should be used for cancellation), wait lets the thread be notified.
If you call Thread.sleep() while holding a lock or from inside a synchronized block/method, any other threads that reach that lock will wait until the first thread resumes and releases the lock.
However locks/synchronization are not global, any threads that don't reach the locks held by the sleeping thread can run without issue.
If other thread can't get the lock to run while this thread is going to sleep, then what's the purpose for this thread to go sleep at first place?
The only person who can answer that question is the person who wrote the code that runs in the thread.
Was that you?
As Nathan Hughes said, it practically never is a good idea for a thread to sleep() while holding a mutex lock. To take that idea a little further: It almost never is a good idea for a thread to do anything that takes more than a microsecond or so while holding a mutex lock. If you find yourself writing code that waits for something while keeping a lock locked, then that's a sign that you might need to re-think the architecture.
Also, there are not many good reasons for calling sleep() at all.
In Java, a thread can go to sleep so that it won't hog the process and other thread can get chance to run.
That's not really what sleep() is for. In most cases, when a thread doesn't need the CPU, it will block in a wait() call or in some xyz.await() call (where xyz is a queue or a semaphore or a latch or some other higher-level synchronization object).
The sleep() function is a low-level, primitive that your program can call in order to meet real-time requirements. But most programs with real-time requirements can make use of higher-level facilities such as java.util.concurrent.ScheduledThreadPoolExecutor
or javax.swing.Timer. If you start by writing your own sleep() calls, without first investigating the higher-level objects, then you may be re-inventing a wheel.
For the following code notifyAll() will hold the lock until done, even when the timeout has reached, this block doesn't hold the lock and has to wait for the notifyAll() block to be finished.
Then what's the meaning of the timeout in wait(timeout) if after the timeout is done we still have to wait for the lock? Also - how to change the code so that the timeout will have meaning?
// one thread
synchronized (lock) {
lock.wait(timeout);
}
// second thread
synchronized (lock) {
// do some processing actions.......
lock.notifyAll();
}
You are indeed correct that the waiting thread actually goes through 2 types of wait: wait for an explicit 'notify/notifyAll', and then wait for an opportunity to get the synchronization lock.
The hope is, that most other threads that use 'synchronized' will only hold the synchronization lock for a brief time. That's a very strongly recommended practice. A private case of it is the thread that calls 'notifyAll' - this is a very short action, and the synchronization block is existed very quickly.
To summarize: the thread might be stuck on 'lock.wait' for a long time (e.g. "waiting for a customer to arrive" - this could take hours, and you might consider a timeout after which you despair of business). However, once the notification arrives and it competes on 'synchronized' - this competition should be brief, so brief that it's not worth it to consider timeout. However, this relies on the good will of your fellow programmers, that should only use synchronized for short blocks (e.g. avoiding a race condition in that fraction of a second when you're updating a variable). It's a matter of good practice.
The wait's timeout has a good meaning. Just read and JavaDoc and think about it. Not sure why you think it has no meaning here, I guess you just got confused.
Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
The current thread must own this object's monitor.
Object.wait(long)
There are situations, where lock.wait() waits for a resource, which may never be available (lock.notify() is never called). For example, responce from the remote computer will never be recieved if it is crashed(or network is crashed).
One choice in these situation is to wait forever, allowing user to interrupt waiting by hands.
Another choice is to use lock.wait(timeout) to wait for a limited amount of time, assuming resource as inaccessible after that amount is expired. In that case(after timeout is expired) program can choose another way to complete task. Or program can simply exit and allow other programs to do their work.
Without taking spurious wakeups into account, usage is simple:
if(!condition)
{
lock.wait(timeout);
if(!condition)
{
//timeout expired while waiting
}
}
// 'condition' is true now
I've got some code that looks like the following:
while (this.conditionIsNotYetMet){
if (timeout()) break;
// Don't do anything, just wait till the condition is
// filled by a different thread or timeout occurs.
}
performSomeCode(); // this code relies on the condition having been met
The code works - eventually the other thread fills the condition, and the code executes.
I'm curious as to whether or not it would be a good idea to throw in a Thread.yield() - it seems to be correct either way, and at this stage I can't feel a performance difference - but I'm concerned that in the future it might make a difference, e.g. on a different platform.
i.e. code would become
while (this.conditionIsNotYetMet){
if (timeout()) break;
Thread.yield(); // <---- CHANGE IS HERE!!!!
// Don't do anything, just wait till the condition is
// filled by a different thread or timeout occurs.
}
performSomeCode(); // this code relies on the condition having been met
I'm aware that there's probably a much more formal way to achieve this pattern using locks or AsynchronousTasks, but this solution works well at the moment and is clear enough, so why change?
yield() is useful in the cases where you are seeing stagnation on other threads. In other words, you have a very active thread that's somehow always taking priority over some other thread that never really gets to do anything. Calling yield() from your active thread forces it to give change to another running thread.
If your program is as simple as your example, you probably do not need to call yield, plus depending on how timeout() is implemented (if it has a Thread.sleep() or Object.wait() inside) it will also implicitly result a context switch just like yield would.
So, you do not need to write it, but you're probably getting the effects of it already anyway.
PS: As Extreme Coders points out, you probably want to use a wait-notify pattern, here's an example
No, you should almost never use yield() at all, and definitely not for waiting on a condition to become true. You should instead look into a "real" concurrency control mechanism like a Condition (which causes the thread to sleep until awoken by another thread) or a CountDownLatch (which causes the thread to sleep until a certain number of signals have happened).
Calling yield() is just a hint to the OS and unless there is a thread waiting it is likely to do nothing. If you want to give the CPU a break you can call Thread.sleep(10); for 10 ms, or shorter if you like.
BTW Given you are waiting for a timeout you could call
Thread.sleep(timeUntilTimeoutInMilliSeconds);
while(!anotherThread.isDone());
or
while(!anotherThread.isDone())
Thread.sleep(5);
If you really need to wait for a thread to complete, use
anotherThread.join()
(You may want to consider specifying a timeout in the join call.)
You definitely shouldn't tight-loop like your first snippet does... and sleeping for 5ms is barely better.
If you can't use join (e.g. you're waiting for a task to complete rather than a whole thread) you should look at the java.util.concurrent package - chances are there's something which will meet your needs.
IMHO, avoid using such logic altogether. Instead, perhaps implement some sort of notification system using property change listeners.
As others have said, it's better to just use join in this case. However, I'd like to generalize your question and ask the following:
In general when a thread is waiting for an event that depends on another thread to occur is it better to:
Use a blocking mechanism (i.e. join, conditional variable, etc.) or
Busy spin without sleep or
Busy spin with sleep?
Now let's see what are the implications for each case:
In this case, using a blocking call will effectively take your thread off the CPU and not schedule it again until the expected event occurs. Good for resource utilization (the thread would waste CPU cycles otherwise), but not very efficient if the event may occur very frequently and at small intervals (i.e. a context switch is much more time-consuming than the time it takes for the event to occur). Generally good when the event will occur eventually, but you don't know how soon.
In case two, you are busy spinning, meaning that you are actively using the CPU without performing useful work. This is the opposite of case 1: it is useful when the event is expected to occur very very soon, but otherwise may occupy the CPU unnecessarily.
This case is a sort of trade-off. You are busy spinning, but at the same time allowing other threads to run by giving up the CPU. This is generally employed when you don't want to saturate the CPU, but the event is expected to occur soon and you want to be sure that you will still be there in almost real time to catch it when it occurs.
I would recommend utilizing the wait/notify mechanism that is built into all Java objects (or using the new Lock code in Java 5).
Thread 1 (waiting for Thread2)
while(!thread2.isDone()) {
synchronize(thread2.lockObject) {
thread2.lockObject.wait();
}
}
Thread 2
// finish work, set isDone=true, notify T1
thread2.lockObject.notify();
'lockObject' is just a plain (Object lockObject = new Object()) -- all Java objects support the wait/notify calls.
After that last call to notify(), Thread1 will wake up, hit the top of the while, see that T2 is now done, and continue execution.
You should account for interrupt exceptions and the like, but using wait/notify is hugely helpful for scenarios like this.
If you use your existing code, with or without sleep, you are burning a huge number of cycles doing nothing... and that's never good.
ADDENDUM
I see a lot of comments saying to use join - if the executing thread you are waiting on will complete, then yes, use join. If you have two parallel threads that run at all times (e.g. a producer thread and a consumer) and they don't "complete", they just run in lock-step with each other, then you can use the wait/notify paradigm I provided above.
The second one.
Better though is to use the join() method of a thread to block the current thread until it is complete :).
EDIT:
I just realised that this only addresses the question as it applies to the two examples you gave, not the question in general (how to wait for a boolean value to be changed by another Thread, not necessarily for the other Thread to actually finish).
To answer the question in general I would suggest that rather than using the methods you described, to do something like this I would recommend using the guarding block pattern as described here. This way, the waiting thread doesn't have to keep checking the condition itself and can just wait to be notified of the change. Hope this helps!
Have you considered: anotherThread.join() ? That will cause the current one to be 'parked' without any overhead until the other one terminates.
The second is better than the first, but neither is very good. You should use anotherThread.join() (or anotherThread.join(timeout)).
Neither, use join() instead:
anotherThread.join();
// anotherThread has finished executing.
What exactly happens when there is nothing on the queue and a take() is called. The API says the method will wait but does that mean the CPU spins checking for empty/not empty until an item is on the queue or does it mean that the thread yields and will be awoken by an interrupt? If it is the case of the former, I would probably want to see if the queue is empty and if it is call thread.yield() to give up processor time. My question is really do I need to call yield or does some inner mechanism handle that for me?
Secondly, what is the interrupted exception meant for? If I understand correctly it means that if thread A is executing this method and is waiting for input and another thread B calls threadA.interrupt() then thread A will catch the interrupted exception and presumably pause execution, if it is nice. Is that the correct way of thinking about it?
Note that BlockingQueue is an interface. So what follows is implementation dependent. If you look at the source code for (say) LinkedBlockingQueue, the source for take() calls lockInterruptibly() on a RentrantLock. From the doc for this:
If the lock is not available then the
current thread becomes disabled for
thread scheduling purposes and lies
dormant until one of two things
happens:
* The lock is acquired by the current thread; or
* Some other thread interrupts the current thread, and interruption of
lock acquisition is supported.
I suspect there's be some wait()/notify() or similar going on. Will it spin the CPU ? No (check via top or similar)
Re. your question on interrupts, the Java Specialist newsletter had a very interesting article on interrupt() and catching/handling the InterruptedException.
Read the article, but essentially if you catch the exception, you reinterrupt:
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt(); // very important
break;
}
The wait() call does not spin, it typically uses OS services to wait for an event/condition - which puts the thread to sleep until the condition/event is signaled again. No processor time is used while waiting.
You typically get the interrupted exception if the thread is blocking in a wait() call, and another thread calls interrupt() on that blocking thread, just like you said.
It is considered a bad practice to call yield() as it cannot ensure niceness - you may call it and the scheduler instantly returns to your thread as it were a no-op. Use timed waits (e.g. wait(1000)) instead.
Interruptions are a safe way to signal a thread that you want something from it - stop processing, wake up and respond to something, etc.
In general, these things depend on your concrete scenarios. Java has some nice features about concurrency which can be more applicable to a situation.