java-在同一对象上同步两次?
我想知道如果在同一个对象上同步两次,在Java中是否会出现任何奇怪的行为?
场景如下
pulbic class SillyClassName {
object moo;
...
public void method1(){
synchronized(moo)
{
....
method2();
....
}
}
public void method2(){
synchronized(moo)
{
doStuff();
}
}
}
两种方法都使用该对象并对其进行同步。 当第一个方法调用第二个方法时,它会被锁定而停止吗?
我不这么认为,因为它是同一个线程,但是我不确定是否可能会出现其他任何奇怪的结果。
6个解决方案
69 votes
重入
同步块使用可重入锁,这意味着如果线程已持有该锁,则它可以重新获取它而不会出现问题。 因此,您的代码将按预期工作。
请参阅Java教程页面的底部“固有锁定和同步”。
要引用截至2015年1月的价格…
重入同步
回想一下,一个线程无法获取另一个线程拥有的锁。 但是线程可以获取它已经拥有的锁。 允许一个线程多次获取相同的锁将启用重入同步。 这描述了一种情况,其中同步代码直接或间接调用也包含同步代码的方法,并且两组代码使用相同的锁。 如果没有可重入同步,则同步代码将不得不采取许多其他预防措施,以避免线程导致自身阻塞。
Leigh answered 2020-02-15T09:04:57Z
4 votes
我认为我们必须对您尝试使用的重入锁。 这是[http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html。]中的摘录。
可重入锁是什么意思? 简单地说,有一个与锁相关联的获取计数,并且如果持有锁的线程再次获取它,则获取计数将增加,然后需要释放两次该锁才能真正释放该锁。 这与同步的语义相似。 如果线程进入由该线程已拥有的监视器保护的同步块,则该线程将被允许继续执行,并且当该线程退出第二(或后续)同步块时,该锁不会被释放,而只会被释放 当它退出第一个同步块时,它将进入该监视器的保护范围。
尽管我还没有尝试过,但是我想如果您想做上面的事情,则必须使用重入锁。
Praveen Mookoni answered 2020-02-15T09:05:27Z
2 votes
Java似乎完全支持同一线程在一个对象上的嵌套锁。 这意味着,如果一个线程在一个对象上具有外部和内部锁,而另一个线程试图在同一对象上锁定,则第二个线程将被挂起,直到第一个线程释放了两个锁。
我的测试是在Java 6 SE下完成的。
Odell Damon answered 2020-02-15T09:05:52Z
1 votes
没问题。 在您的示例中((一旦修复了代码以摆脱将得到的编译警告;)),同步确保了method1和method2中的块不会同时执行。
这就是同步的要点。 :)
编辑:对不起,您的问题部分遗漏了,但是Phill回答了。 总而言之,单个线程无法使其自身死锁。
Jack Leow answered 2020-02-15T09:06:22Z
1 votes
在Java中,方法上的synchronized关键字基本上在当前对象上同步,因此实际上它在隐式地执行您上面建议的操作。
在一个方法中先同步一个对象,然后在另一方法中先同步一个对象,您将不会遇到问题,因为正如您所说,当前线程已经对该对象保持了锁。
answered 2020-02-15T09:06:47Z
0 votes
不,如果被第一个调用,第二个方法将不会停止。 不会有奇怪的结果发生(检查锁的开销很小。这无关紧要。从Java 6开始,您在JVM中进行了锁粗化-[http://java.sun.com/performance/reference/whitepapers/6_performance。 html])
例如,看一下java.util.Vector的源代码。 同步方法中有许多对其他同步方法的调用。
RuntimeException answered 2020-02-15T09:07:12Z