java 使用同步语句的可重入同步行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5787957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:45:35  来源:igfitidea点击:

Reentrant synchronization behavior with synchronized statements

java

提问by Muthu

I have two methods in a java class that both have a block of code that synchronize using the same object. I understand that in the JAVA synchronization scheme locks acquired by a thread are reentrant. With this can i safely say the below piece of code will not cause any issues in all cases?

我在 java 类中有两个方法,它们都有一个使用相同对象同步的代码块。我知道在 JAVA 同步方案中,线程获取的锁是可重入的。有了这个,我可以安全地说下面的代码在所有情况下都不会引起任何问题吗?

public class Someclass  
{  
  private static final Object LCK_OBJ = new Object();  
  //.....

  publc void method1()  
  {  
    //some code....  
    synchronized(LCK_OBJ)  
    {  
        //some sychronized code.  
        method2(..);  
    }  
    //some more code....  
  }  

  protected static final void method2(..)  
  {  
      Someclass ref = null;  
      //some code which gets different other references of SomeClass in a loop....  
      ref.method3(..);  
  }  

  publc void method3()  
  {  
    //some code....  
    synchronized(LCK_OBJ)  
    {  
      //some sychronized code.  
    }  
    //some more code....  
  }  

}//end of class    

采纳答案by Tomasz Stanczak

Yes you can, but this code won't compile: you are calling an instance method "method3" from a static method "method2". Other than that: if a thread has managed to aquire a lock in "method1" if will still have the lock in "method3".

是的,您可以,但此代码无法编译:您正在从静态方法“method2”调用实例方法“method3”。除此之外:如果一个线程已经设法在“method1”中获得了一个锁,如果仍然在“method3”中拥有这个锁。

回答by Peter Lawrey

Yes, synchronized blocks are reentrant. ReentrantLock is also reentrant and if you want to code the blocks yourself, you might want to use that instead as it has more flexibiliy/functionality.

是的,同步块是可重入的。ReentrantLock 也是可重入的,如果你想自己编写代码块,你可能想改用它,因为它具有更多的灵活性/功能。

I would make sure any lock is finalIf a lock object cannot be final, it is almost certainly a bug (or a source of confusion)

我会确保任何锁是final如果一个锁对象不能是最终的,它几乎肯定是一个错误(或混淆的根源)

For comparison purposes, not all locks in Java are reentrant. FileLock is not as it passes the request directly to the OS.

出于比较的目的,并非 Java 中的所有锁都是可重入的。FileLock 不是因为它将请求直接传递给操作系统。

回答by WhiteFang34

Yes, the same thread can enter a synchronizedblock on the same lock multiple times. Be careful not to acquire other locks in a different order, otherwise you can cause a deadlock.

是的,同一个线程可以synchronized多次进入同一个锁上的一个块。注意不要以不同的顺序获取其他锁,否则会导致死锁。

回答by vineet

Though this code wont compile as already mentioned , lets consider the case that method2 is not static.A call from method1 to method2 and then to method3 is good example of reentrant synchronization.When a thread initiates, it creates a new stack with the run() at the bottom of the stack.Since the call to method1 comes from run() it is added in the stack above run() and then goes the method2 and method3 in the stack. Also, as the object lock is taken by method2 on the stack , the lock is maintained on all synchronized api called .The release of the lock is initiated by unwrapping the top most method (method3 in this case)in the stack till the actual api is reached which calls synchronize.

虽然这段代码不会像前面提到的那样编译,但让我们考虑方法 2 不是静态的情况。从方法 1 到方法 2 再到方法 3 的调用是可重入同步的一个很好的例子。当一个线程启动时,它会创建一个新的堆栈与运行( ) 在堆栈的底部。由于对 method1 的调用来自 run(),因此它被添加到 run() 上方的堆栈中,然后转到堆栈中的 method2 和 method3。此外,由于对象锁由堆栈上的 method2 获取,因此该锁在所有调用的同步 api 上维护。锁的释放是通过解包堆栈中最顶部的方法(在本例中为method3)直到实际api达到哪些调用同步。