Nested synchronized keyword

2019-02-02 23:55发布

问题:

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?

回答1:

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.



回答2:

If a thread owns the lock on this, it will go into other synchronized methods/block like hot knife in butter.



回答3:

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.



回答4:

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.



回答5:

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
}


回答6:

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         
         }
}