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.
Related
We have an OSGi based application, which offers a central service interface to other bundles, one method of the service imlementation is synchronized:
MyServiceImpl implements Service {
#Override
public synchronized doSomething() {
}
}
Multiple threads access this service (e.g. a camel route and a webservice call) and call the doSomething() method at the same time. So, nothing special here, Java should synchronize the method call here.
Anyway, we face the problem, that our system is stuck: A thread dump tells us, that some thread is in state "Blocked" because another Thread holds a lock on the service implementation object. Each thread is trying to call the doSomething() method and the one thread is waiting forever, that the lock is released.
My question is, how can that happen, here is nothing special, I can not figure out, why the lock is not released !?
Deadlocks should normally no happen with only one lock. The only time you can get a 'deadlock' with one lock is when one thread can monopolize a lock. I.e. it gets it, releases it but grabs it before another thread has a chance. Java synchronized is not a fair lock.
However, the simplest case of a deadlock is when you have lock A and lock B. A thread T1 gets lock A while simultaneously thread T2 gets lock B. T1 does some work and tries to get lock B. However, B is held by T2 so it blocks. T2 does some work and tries to get lock B. It is locked by T1 so T2 blocks.
T1 waits for A which is held by T2 and T2 waits for B which is held by T1. So neither can make progress and release their lock.
So I expect that your doSomething() method is actually getting another lock in its body by calling out to other code.
There is a common solution and that is to create a list of your locks and when you need multiple locks you always get them in the same order. In that case, no deadlocks can happen. However, the problem is that you can rarely create such a list because today we almost always use code from others.
For this reason, the synchronized on methods was a bad idea. Synchronized is a low-level construct; you should only use it on very small blocks of code that do not call foreign code. I.e. you update a data structure but don't call out. When you are in a synchronized block and you call other services you are playing Russian roulette. If you need to lock over larger times use the classes in java.util.concurrency that allow timeouts. Timeouts are the simplest solution to deadlocks.
There are many patterns to properly use synchronized. That said, it is a very complicated area. I learned everything I know about locking (and so much more) from Transaction Processing. A good book about Java concurrency is the Java Concurrency in Practice.
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've a simple question but couldn't manage to find a proper answer. Imagine we have;
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
What about the code after sync. block here? I mean sync. blocks are used to reduce scope of lock but here the code after it ( namelist.add(name) ) will be blocked, right ?
Assume thread A called this function above but it's gonna wait for 'this' lock to be released by thread B which had the lock before on some other method. Now, I wondered if the execution will resume from B's nameList.add(name) method while thread A is waiting on 'this' lock object - since nameList.add(name) is not in the sync block.
Now, I wondered if the execution will resume from B's nameList.add(name) method while thread A is waiting on 'this' lock object - since nameList.add(name) is not in the sync block.
No, the thread executing the method can't just skip over the block and execute the remaining part of the method. What it will do is block until it can acquire the monitor on this, then execute the synchronized block, then release the monitor on this, then add the string to the nameList.
If concurrent threads execute this, there's no guarantee of which threads will insert into the nameList first. It's possible that between the time that a thread releases the monitor on this and the time that it adds to the nameList one or more other threads might barge in and add to the list.
Also whatever nameList is implemented as needs to be a thread-safe collection, so that concurrent changes don't cause errors and so that changes are visible across threads. If nameList is an ArrayList or a HashSet, for instance, then this would not be safe.
In principle, keyword synchronized does following two things:
Code guarded by the synchronized keyword cannot be executed
simultaneously by more than one thread;
.. it controls the visibility of data (variables) between threads;
In your example, the code which is not in synchronized scope would be accessible by all other Threads which call this method;
Assuming the operations which is out of scope is writing operation, you'd (generally) want it to be synchronized to reduce any anomalies which may creep up.
synchronized(this) will block if and while another thread is inside this block. If the thread leaves this block, one waiting thread has a chance (amongst other waiting threads) to enter the block. namelist.add() is executed outside the synchronized scope, so it may be executed in parallel with other threads.
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
I'm synchronizing on the object of the thread like this:
synchronized(threadObject){
try{
threadObject.interrupt();
}catch(Exception ex){
//catch error here.
}finally{
threadObject.notifyAll();
}
}
Now, my questions are:
It is possible to interrupt a thread
inside a synchronized block whose
object that was synchronized was the
thread to be interrupted? Like in
the sample code.
Can I still notify other threads
holding the interrupted thread's
object? Like in the sample code.
It is possible to interrupt a thread inside a synchronized block whose object that was synchronized was the thread to be interrupted? Like in the sample code.
Yes. I can't see why that wouldn't work. The synchronized keyword is quite orthogonal to the interrupt method. (Note that contrary to await and notify, you're not required to own the objects monitor when calling interrupt.)
Can I still notify other threads holding the interrupted thread's object? Like in the sample code.
Yes, you can call notifyAll on any object as long as you own the objects monitor. Again, the wait/notify-mechanism is quite orthogonal to the interrupt method.
Your question seem to indicate that you've misunderstood the use of synchronized. The usual use-case is to synchronize on an object representing some resource which you like to avoid concurrent access to. The thread itself rarely represent such resource.
The object works as it normally does. The only stipulation is that other threads that synchronize on threadObject's monitor will block until you're complete with your thread. So yes, you can do both of those.
Yes: But you don't really need to have the lock before calling interrupt.
Yes
The answer to both questions is yes.
However, there is something a bit strange about your example. I've never come across a case where you would use a Thread as a primitive lock. And it what you are doing in the example doesn't seem to achieve anything.
If threadObject is the same as Thread.currentThread(), then the call to interrupt() will just set this thread's interrupted flag ... which be noticed in that code fragment.
if threadObject is some other Thread object then that thread will be interrupted. But we can't see (here) the code that that thread will be executing, and we don't know if it will be waiting on threadObject. If not the interrupt() and notify() well got to different threads ...
The bottom line is that you wouldn't normally use a Thread object as a lock, and you wouldn't normally send use an interrupt() as an ersatz notify().
(Maybe this example is not intended to represent a real use-case.)