I have a quick question. I basically have a synchronized method which does some task when called upon so.
I use multi threads and sometimes, when the task is being executed by one thread, the thread hangs causing the synchronized method to be in blocked state indefinitely. This doesn't allow the next process to access the block.
Is there a way where I can set a timer, where after a said time ( say 60 seconds) the synchronized method gets released so other threads can still continue and not get blocked?
If there is a way, can someone please put up a sample code.
Thanks in advance!
You can use a lock instead of synchronized keyword
To be able to forcefully unlock a lock owned by another thread, you can use following implementation https://stackoverflow.com/a/16492269/5313017
The method would be like following
public void synchronizedMethod() {
if(!lock.tryLock(10, TimeUnit.SECONDS)){
lock.forceUnlock();
}
doStuff();
lock.unlock();
}
Related
What happens if a thread executing a synchronized method suspends? Will other Threads get the lock and proceed with another synchronized method in the same class..?
Suppose the code is like:
class Test{
public synchronized void methodA(){
//methodA
}
public synchronized void methodB(){
//methodB
}
}
If ThreadA execute methodA(). And while executing the method if it get suspended implicitly by the OS. Will another Thread, say ThreadB can get the lock and execute methodB()? or is it possible only after the ThreadA completes its work with methodA()?
No, it won't force the thread to relinquish the lock since it would break the whole idea of synchronization. It is possible to exit the monitor via wait method call on the object (declared in the Object class) to give other threads a chance to enter it .
Following text from book Java - The Complete Reference should help :
This was done because suspend( ) can sometimes cause serious system
failures. Assume that a thread has obtained locks on critical data
structures. If that thread is suspended at that point, those locks are
not relinquished. Other threads that may be waiting for those
resources can be deadlocked.
I stumbled upon a piece of code in an Android Service class that has a synchronized block with a wait statement.
The code is as follows:
public class MyService extends IntentService{
protected void onHandleIntent(Intent intent){
synchronized(this){
try{
wait(10000);
}catch(InterruptedException e){
e.printStackTrack();
}
String message = intent.getStringExtra("Message");
showMessage(message);
}
}
}
Does the above code means that any number of threads can enter the synchronized block? I know that sleep puts the Thread in a Blocked state. Is this the same with a Thread calling wait()?
Basically when I pass a text to the Service, I want the Service to wait for 10 seconds then display the message in the LogCat.
I have never used wait() anytime so could anybody explain to me what the above code is doing?
Your statement "any number of threads can enter the synchronized block" is false.
Theoretically, if one thread is inside the synchronized block, this prevents other threads from entering. Which is not possible in the case of IntentService because IntentService uses a single worker thread to handle the workload.
Calling wait() is a thread synchronization method, not a delay method. This is different from calling sleep() which just blocks the thread for a specific amount of time. When you call wait() this blocks the thread until another thread calls notify(), which is used to coordinate activities among multiple threads. wait(10000) blocks the thread until either notify() is called from another thread OR until the timeout expires (in this case 10 seconds). So this looks like there should be another thread somewhere which is calling notify() on the IntentService object to wake it up.
There is an additional complexity here associated with the use of notify() and wait(). In order to call either of these methods, a lock on the object's monitor must first be obtained (by the use of synchronized). This means that calls to wait() and notify() must be within synchronized blocks or within synchronized methods that are synchronized on the object.
The thread that calls wait() actually releases the lock on the object. This means that the thread is blocked inside a synchronized block/method but it does not have a lock on the object while waiting. Once notify() is called (or the timeout has expired), the thread will regain the lock on the object and continue executing.
For more information about using notify() and wait() in Java, search for these terms and read about it.
This code is pretty convoluted if all it is supposed to do is delay 10 seconds and then write a something to logcat. You could just call sleep() instead of wait() which would not require the synchronized statement. However, as another poster noted, if this Service is called very often, this will create a backlog as each and every call to onHandleIntent() will be delayed by 10 seconds and since there is only 1 worker thread, all calls are serialized. Example: a call to startService() is made at 10:00:00, the entry in the logcat will appear at 10:00:10. If another call to startService() is made at 10:00:01, that entry will not appear in the logcat until 10:00:20, because the second call to onHandleIntent() will not happen until 10:00:10.
Part of your question deals with multithreading, which is a pretty complicated topic. I recommend starting out with a tutorial like this one to get those answers.
The above code will serve to delay log entries by 10 seconds. However, IntentService only has 1 worker thread, so successive requests will get backlogged if they occur more often than once every 10 seconds.
Because only 1 worker thread is involved, using synchronization is really the wrong answer. Why not ditch the IntentService, and just do all this on the UI thread, using a CountDownTimer?
final String msg = intent.getStringExtra("Message");
new CountDownTimer(10000, 10000) {
#Override
public void onTick(long millisUntilFinished) {}
#Override
public void onFinish() {
showMessage(msg);
}
}.start();
That way, you can create the appearance of parallel execution, without the complexity of multithreading, by taking advantage of Android's built-in message queueing system.
Unfortunately I'm not going to be able to give full context to this, since there's too much complexity in the surrounding code. The short of it is this:
I have a block of code that's waiting on a lock:
synchronized (lock) {
lock.wait();
}
Which works as expected. Fairly straightforward -- it acquires the lock, releases it when it starts waiting, another thread acquires the lock and then notifies on it.
However, as soon as I provide a timeout, the behavior changes entirely.
synchronized (lock) {
lock.wait(60000L);
}
Again, should be fairly straightforward (and this works as expected in several other places in the code). However, in this one case, execution basically halts until the timeout occurs. My only guess as to what seems to be happening is it's not releasing the lock when it enters the wait -- the notifier is never able to acquire the lock, so the wait sleeps until it times out. And even worse, it's a blocking sleep -- no other threads are able to wait on the lock and it forces the execution to be entirely synchronous.
Anyone have any ideas as to what might be happening here? It's a fairly simple function and there's nothing weird going on with nested synchronization blocks at any point. Considering that by providing no timeout it should wait indefinitely, if the notifier itself was broken the code would be hanging forever, but that's not the case. It only stops working once the timeout is provided.
Any thoughts would be greatly appreciated.
OS: OS X 10.8.5
JDK: 1.6.0, 1.7.0.45 and 1.7.0.67
Your example does not show a while() loop around the wait() call. That suggests that you may not completely understand the use case for wait and notify. Here's one example:
// This object is used to synchronize *EVERY* method
// that can change the value of count.
final Object lock = new Object();
int count;
void waiter() {
synchronized(lock) {
while(count <= 0) {
lock.wait();
}
//do something that you are only allowed to do
//when count > 0.
}
}
void notifier() {
synchronized(lock) {
count++;
if (count >= 0) {
lock.notify();
}
}
}
[Edit: Added this paragraph, thank's Nathan Hughes for reminding me that...] The wait() call is in a loop because the wait()ing thread still has to re-acquire the lock after the lock has been notified: if thread A is waiting for the condition to become true, and thread B makes the condition true and calls notify(); there's no guarantee that thread C won't get the lock first, and make the condition false again before the wait() call is able to return.
Also, wait() is allowed to return even when the object has not been notified (that's called a "spurious wakeup").
The condition-to-be-waited-for is explicit in the code (i.e., count > 0).
Nothing changes the condition-to-be-waited-for except when synchronized on the same lock object that is used for wait() and notify() calls.
Irrespective of whether you provide a timeout or not the wait method on an object releases the lock held on the object by the current thread as commented by John.
With the code that you have given and based on your description of scenario my guess is that the moment lock.wait(60000L) is executed JVM releases the lock on the object meanwhile any other thread which is in runnable/running state might be picked up and if they are synchronizing on the same object then they might take the lock before your notifier thread would take the lock.
This behaviour is difficult to debug as it depends on JVM profiler to pick which thread should be run. So as you explained just when your lock.wait(60000L) is executed it need not always be that the notifier thread alone should pick up the lock on the common object . If there is any other thread which is also waiting on the common object it can very well get the lock finally leading to notifier thread not being able to get the lock and hence the lock.wait(60000L) gets timedout.
Whenever you use lock.wait(..) you have to use the lock.notify() or lock.notifyAll(). Make sure you use that where it makes sense in your logic and it will 'wake up' the lock before the timeout (considering the timeout value you put is enough). Here it's some guide for its usage, i hope its useful: http://www.javamex.com/tutorials/wait_notify_how_to.shtml
In a first Java thread I have:
while (!isDone) {
try {
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
doSomeVeryLongRunningTask();
}
In another thread, I want to send a notify signal:
synchronized (thr1) {
thr1.notify();
}
However, if the doSomeVeryLongRunningTask() method is running, I don't want the second thread to get blocked. I only want to notify the first thread if it is waiting so that the second thread can continue it tasks without getting locked.
How might I fix the code above to accomplish this?
They problem you want to fix does not exist. synchronized blocks will block the thread only if another thread is already inside a synchronized block synchronizing on the same object. Since your doSomeVeryLongRunningTask() will be called outside the synchronized block the notifying thread will never get blocked if the other thread is inside the doSomeVeryLongRunningTask() method.
But this raises another problem. You seem to be thinking, that wait and notify invocations are always paired. This is not the case, you may call notify as often as you wish without anyone listening to it. It might be also the case that a wait invocation returns “spuriously”, i.e. for no apparent reason. You therefore need to define another “hard condition” which is defined by a state that is modified and checked inside the synchronized block.
E.g. inside the class whose instance you have in your thr1 variable, you can define a boolean flag:
boolean condition;
Then you modify you waiting method like this:
while(!isDone) {
try {
synchronized(this) {
while(!condition) wait();
if(isDone) break;// skip doSomeVeryLongRunningTask()
condition=false;
}
} catch(InterruptedException e) {
e.printStackTrace();
}
doSomeVeryLongRunningTask();
}
And the notifying code to:
synchronized(thr1) {
thr1.condition=true;
thr1.notify();
}
This way your notifying code still won’t get blocked (at least never for a significant time) but the waiting thread will wait for at least one notification to happen within one loop cycle.
It seems what is blocking your program is not the notify() (it doesn't block ever) but the two synchronized blocks that are synchronizing on the same object.
I don't think there is a workaround to what you ask. Check this link to know why: http://javarevisited.blogspot.com/2011/05/wait-notify-and-notifyall-in-java.html
The notify() call doesn't block. Only wait() blocks. You can call notify even if there isn't another thread waiting, but then make sure your algorithm is correct. If you expect to notify only once, then another thread arriving after the notify will wait() forever.
The advised pattern is to use notifyAll() AND to have ALL waiting threads check their wake-up condition each time they are notified AND before starting the first Wait.
The synchronized in modern Java is about as fast as --i, because this is about what is internally happening thanks to hardware compareAndSet mechanisms. The only moment this slows down noticeably, is when more than one thread is arriving at the synchronized block and therefore at least one has to wait.
I wanted to know if it's possible to use wait() on a synchronized piece of code without using notify(), something like this:
wait_on(B):
synchronized(B.monitor) {
B.count--
while (B.count > 0) { /* wait */ }
}
Thanks in advance
You need notify or notifyAll to awaken the thread from its wait state. In your sample the code would enter the wait and stay there (unless interrupted).
Know the difference between wait, yield, and sleep. Wait needs to be called in a synchronized block, once the wait is entered the lock is released, and the thread stays in that state until notify is called. Yield returns the thread to the ready pool and lets the scheduler decide when to run it again. Sleep means the thread goes dormant for a fixed period of time (and from there it goes to the ready pool).
Make sure you call wait on the same object that you’re synchronizing on (here it’s B.monitor).
No! Only option is to wait with a timeout, which surely will not help you.
If you change the /* wait */ into a call to wait(), and no one will call notify() or notifyAll(), then this thread will never wake up...
If it is a barrier that you want, you will need to notifyAll your other threads:
wait_on(B) {
synchronized(B.monitor) {
B.count--
while (B.count > 0) {
B.monitor.wait()
}
B.monitor.notifyAll();
}
}
Regards,
Pierre-Luc