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

我在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 

是的,你可以,但是这段代码不能编译:你从静态方法“method2”调用实例方法“method3”。 除此之外:如果一个线程设法在“method1”中获取一个锁,如果仍然在“method3”中有锁。

是的,同步块是可重入的。 ReentrantLock也是可重入的,如果您想自己编写块,您可能希望使用它,因为它具有更多的灵活性/function。

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

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

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

虽然这段代码不会像前面提到的那样编译,但我们考虑一下method2不是静态的情况。从method1到method2然后再调用method3是重入同步的好例子。当一个线程启动时,它会创建一个带有run的新堆栈(在stack的底部。由于对method1的调用来自run(),它被添加到run()之上的堆栈中,然后是堆栈中的method2和method3。 此外,由于对象锁定由堆栈上的方法2占用,所以在所有同步的api上都会保持锁定。锁定的释放是通过展开堆栈中最顶层的方法(在这种情况下为method3)来启动,直到实际的api到达哪个调用同步。