Java在可重入同步块中等待/通知

时间:2015-04-16 14:01:47

标签: java wait synchronized reentrancy

我对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方法通知等待此对象监视器的线程唤醒。然后等待,直到它可以重新获得监视器的所有权并恢复执行,“

所以我认为第二种情况是正确的,但我可能是错的。所以我错过了什么,或者我只是遇到了一个冗余的同步块,可以很容易地从代码中删除?

1 个答案:

答案 0 :(得分:6)

if之后没有必要重新获得锁定。

wait()也将完全释放锁定(否则会很容易发生死锁)。

我可以看到的第二个synchronized的唯一原因是,它之前使用过另一个对象而有人修改它以便错误地使用相同的this