我对Java synchronized()块的理解是,如果一个线程已经拥有一个对象的锁,它就可以在同一个对象上输入同步的另一个块(重入同步)。在下面,我相信JVM使用引用计数来递增/递减线程获取锁定的次数,并且锁定仅在计数为零时释放。
所以我的问题是,如果遇到一段看起来像这样的代码:
synchronized(this)
{
if (condition == WAITING)
{
synchronized(this)
{
condition = COMPLETE;
notify();
try
{
wait();
}
catch(InterruptedException e)
{
}
}
}
else
condition = READY;
}
调用wait()时会发生什么?它只是减少计数,还是释放锁定而不管计数?
在第一种情况下,在我看来,如果发生锁重新进入会产生死锁,因为它仍然拥有锁,因此会在另一个等待它的线程上永远等待。
在第二种情况下,我无法真正看到第二个同步块的重点是什么。
wait()的文档说
“当前线程必须拥有此对象的监视器。该线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。然后等待,直到它可以重新获得监视器的所有权并恢复执行,“
所以我认为第二种情况是正确的,但我可能是错的。所以我错过了什么,或者我只是遇到了一个冗余的同步块,可以很容易地从代码中删除?
答案 0 :(得分:6)
if
之后没有必要重新获得锁定。
wait()
也将完全释放锁定(否则会很容易发生死锁)。
我可以看到的第二个synchronized
的唯一原因是,它之前使用过另一个对象而有人修改它以便错误地使用相同的this
。