I'm just getting started with Threads in Java so this might be a basic question, but I couldn't find the answer online.
I have two threads that can call one synchronized function. The way I understand it, if the second thread calls it while the first thread has already called it, the second thread will wait until the first thread is done before calling it. However, I don't want the second thread to call it at all.
Then the easiest way is to use an explicit lock (ReentrantLock) and call its tryLock() method.
If it returns true, then it means that no other thread has the lock, and the current thread acquired it.
If it returns false, it means that another thread holds the lock, and you should not call the method.
Remember to always call unlock() in a finally block, to make sure the lock is released even in case an exception is thrown.
Related
I'm learning about multiple threading in Java. Following is demo code, and I'm curious about the usage of Thread.yield() inside of the function.
Isn't it a synchronized function, which cannot be called until the running task finishes its work on it? Then what is the difference between inserting Thread.yield() into this block and not?
Demo code:
public class SynchronizeEvenGenerator {
private int currentEvenValue = 0;
/**
* Generate even and return it
* #return
*/
public synchronized int next() {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
}
}
What will happen if Thread.yield() is called in a synchronized function?
As the javadoc for Thread.yield() states:
"[This is a] hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint."
So there are two possibilities:
Nothing happens; i.e. the yield() call returns immediately.
Another thread is scheduled and gets to execute. Eventually, this thread is rescheduled and the yield() call returns.
One thing does not happen. The thread does not relinquish the mutex. Any other thread that happened to be blocked waiting to acquire the mutex will remain blocked.
Isn't it a synchronized method, which cannot be called until the running task finishes its work on it?
Thread.yield is not a synchronized method. (And even if it was, it would be locking the Thread object, not the lock that the synchronized block is currently holding.)
So, in your example, a call to next() is guaranteed to increment the counter by exactly 2. If some other thread calls the next() method, the second call will remain blocked until (at least) after the first call returns.
The javadoc also says this:
"It is rarely appropriate to use this method."
Another question: Will it become an deadlock for thread scheduling
No. The thread that called yield() will eventually be rescheduled.
(Deadlock is a very specific phenomenon (see Wikipedia article) that can only occur when a lock is acquired. When a thread yields, it neither acquires or releases locks, so it cannot cause a deadlock.)
Now, when a thread yields, it might be a long time before it gets scheduled again, especially if there are lots of other runnable threads at the same or higher priority. The net result is that other threads waiting to acquire the lock could held up for a long time. This can unduly increase contention and congestion. But eventually, the yield() call will return, the next() call will return and another thread will be able to acquire the lock.
In short: calling yield() while holding a lock is bad for performance, but it won't directly cause a deadlock.
As the javadoc says, calling yield() is rarely appropriate.
Isn't it an synchronized function which cannot be called until the running task finish it's work on it ?
It can't be running in another thread for the same object.
Then what is the diff between insert Thread.yield() into this block and not ?
The CPU which is running the thread could be context switched to another available thread for any process on the system.
If there is no waiting thread to run, it will make it slower by about 15 - 30 micro-seconds.
c.f. wait(0) which can allow another thread to obtain the lock.
I am learning multi-threading programming in Java, and the most difficult part seems to be inter-thread communication, using wait(), notify() and notifyAll().
I referred to official Javadoc of wait() , reproducing here:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
I got the point that when a thread t calls wait() it immediately releases the lock and then waits; however I am not able to understand what the condition in while loop means? Can't there be a chance before thread t checks for the condition in while loop the condition has been modified by some other thread?
Can anyone tell me what this condition is and what basic things are to be used in while loop for checking the condition?
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.
check below one also for your better clarity.
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.
The problem is the obj might call all waiting threads up by obj.notifyAll(), these woken up threads will enter syncronized code block in an uncertain order, and operate the shared data. So, it is necessary to check condition in while loop.
Suppose you have an empty queue, thread1 and thread2 is waiting to take element from it,
synchronized (obj) {
while (queue.isEmpty())
obj.wait();
... // Perform action appropriate to condition
queue.take();
}
After thread3 putting an element in this queue, and calls obj.notifyAll(), which will call thread1 and thread2 up:
thread1 wakes up first, find the only element in queue, and take it.
thread2 wakes up later, check if there is any element in queue by queue.isEmpty(), and wait()
again.
I am not able to understand what the condition in while loop means?
Literally, it means the logical inverse of the condition that you are waiting to happen.
Can't there be a chance before thread t checks for the condition in while loop the condition has been modified by some other thread?
The assumption1 is that the variables that make up the "condition" are only updated by another thread while it is holding the lock on obj.
Hence, at the point immediately after the while loop, the thread in the code above knows that the condition is now true, and nothing else will change it before it releases the lock.
Now ... obviously ... if some other thread is going to change the variables that make up the condition without holding the lock, then what you are worried about can happen. But that's a buggy program. You have shared variables being updated by different threads without adequate2 synchronization.
1 - The thread has to be holding that lock when it calls obj.notify() or obj.notifyAll(). (If not, you will get an exception.) But the guarded condition will also work if the variables are updated in a separate synchronized block to the notify call. It just makes the code harder to understand ...
2 - In this context, declaring variables as volatile is not sufficient for correct behavior of the guarded condition.
The condition in the head of a while loop can be any expression which resolves in a boolean.
In your example the while loop should suspend the execution of the real method until a certain condition is true.
Let's assume your synchronized method needs to be executed at 12pm and needs thread-safe access to the object obj
Then you head of the while loop would check if the current time is NOT 12pm. If this is true, the method cannot start it's real work. But to prevent blocking resources it will allow other threads to work with obj by calling obj.wait().
When we reach 12pm the condition of the while loop will be false and the thread exists the while loop and execute the rest of your code.
Synchronized blocks in Java is a great feature when working in multiple threads, which is pretty often. I know most of how they work, but would like to be more sure of how they work when combined with wait and notify(All).
Normally when one thread enters an synchronized block, no other thread can enter this block until the first thread has left. This however is not the case when calling wait on the synchronized object. If it did, another thread would not be able to call notify(All), which requires synchronization with the object before it is called.
So does the call to wait take the call out of the synchronization? Or does java just make an exception if it finds notify(All) within a different block? Also when calling wait from one synchronized block and then notify(All) from another, does one thread wait for the other to finish before continuing, if so, which one?
Now I could setup a quick test to answer most of this, that I am aware of. But it is not going to answer the more technical stuff, which I am sure that someone here can. I am not just interested in the what and when, but also the why. Tried searching for some documented info, but could not find anything useful about wait/notify(All).
EDIT:
If others should be interested, this is the test result. If we have Thread1, Thread2 and Thread3 where the first two waits to be release and the third is the one to release them, the order will go like this.
Thread1 enters and calls wait()
Thread2 enters and calls wait()
Thread3 enters and calls notifyAll()
Thread3 finishes, always
The waiting threads however has no specific order. Which one is executed first, is completly random and has nothing to do with the order in which they called wait(). The thread calling notify(All) however will always finish before any waiting threads continues.
Yes, it is somehow special. wait releases the lock acquired in the synchronized block and and suspends it's thread (the thread that acquired the lock) which means other threads will be allowed to acquire the lock and modify the state.
Now notify or notifyAll will wake up the thread/s that were asleep and they reacquire the lock
May I include a synchronized block inside another one for synchronizing another object?
Example:
synchronized(myObjetc1){
// code
synchronized(myObjetc2){
// code
}
}
If so, still, is it a correct technique or is it too risky?
It will be fine if you synchronize in the same order everywhere else.
If some other thread were to execute the following code
synchronized(myObjetc2){
// code
synchronized(myObjetc1){
// code
}
}
you might get a deadlock.
Assuming the variables above are referencing the same objects, consider the following case. The first thread (your code) locks the monitor on myObjetc1. The thread scheduler switches thread context. The second thread (the above code) locks the monitor on myObjetc2. The thread scheduler switches thread context. The first thread attempts to lock the monitor on myObjetc2. It has to wait because the second thread has it. The thread scheduler switches context. The second thread attempts to lock the monitor on myObjetc1. It has to wait because the first thread has it. Boom! Deadlock.
Yes, you can do it.
Till the time you are following lock rules and doing so solves your requirement, its Fine.
However, many times something like this invites DeadLock problem, if done incorrectly.
Is there any way I can stop a thread without using deprecated stop()?
The thread invokes some methods from a potentially badly written class which may contain infinite loops. Since I can't modify this class, I have no control over the loop condition and therefore can't exit normally using interrupt() or any other variable. Is it justified in this case to use stop()?
If you cannot use stop() and cannot fix the code, your only other option is to run the code in another process and kill the process.
In your case, the simplest option is to use Thread.stop()
The problem with the stop() method is that it can leave synchronized objects in an inconsistent state (i.e. if you stop the thread while you're halfway through a synchronized object update, then only part of the object may be updated). If your thread isn't using any synchronized methods / blocks then it's safe to stop it.
If your thread might be using a synchronized block/method, then try to cleanly shut it down before calling stop, e.g. call interrupt on it and then call stop X minutes later if the thread still hasn't stopped (operating on the assumption that the thread is calling a broken method). Just be sure that the thread leaves everything in a consistent state before calling a potentially broken method.