I have this code in Java:
public void doSomeThing() {
synchronized (this) {
doSomeThingElse();
}
}
public void doSomeThingElse() {
synchronized (this) {
// do something else
}
}
Can this code block? I mean, Can this code wait for ever?
As the java documentation describes for Reentrant locking:
a thread can acquire a lock that it
already owns
The second synchronized block is using the same lock and thus will always be useable as the lock has already been aquired in the outer method.
No, there will not be a deadlock.
If a thread owns the lock on this
, it will go into other synchronized
methods/block like hot knife in butter.
In a synchronized block you can re-aquire a lock that you already own. The lock provider (this) will be acquired by the first thread to enter doSomething(). Then in the doSomethingElse() method it will re-aquire it.
The reason to do this? Well there is nothing to say that there is not some other thread entering doSomethingElse from elsewhere. This will prevent any code from executing the block in doSomething() until the thread in doSomethingElse() has released "this".
Edit BTW it can of course block... and it will block any thread that does not own the synchronization object from executing. However it will not (as posted) deadlock.
Lock already obtanied by the thread executing doSomething method, therefore this thread can execute doSomethingElse method.
You need two lock object to create a deadlock situation. In your case, there is only one, therefore it is impossible to create a deadlock.
The synchronized use in both case this
so if the synchronized block in doSomeThing run, you allready have the lock so you can execute the doSomeThingElse method.
If your code is so simple, it is equivalent to :
public synchronized void doSomeThing() {
doSomeThingElse();
}
public synchronized void doSomeThingElse() {
// do something else
}
You have already taken the monitor lock in the first synchronized.
You should always ensure that the concurrency design does not make the performance impact huge.
One way to ensure this is by synchronizing only the required statements/code.
Let's say now your code will look something like this.
public void doSomeThing()
{
synchronized (this)
{
synchronized (this)
{
// do something else
}
}
}
Whereas this is what is required
public void doSomeThing()
{
doSomeThingElse();
}
public void doSomeThingElse()
{
synchronized (this)
{
// do something else
}
}