2012-06-25 102 views
4

如果我在两个方法中使用同步(this),另一个调用另一个方法,我会陷入死锁状态,还是会工作,因为线程已经拥有锁定了?Java对象锁定:调用其他方法时发生死锁?

图片下面的类:

public class Test { 
    public void foo() { 
    synchronize(this) { 
     bar(); 
    } 
    } 

    public void bar() { 
    synchronize(this) { 
     // do something 
    } 
    } 
} 

正如你所看到的,有两种方法foo和酒吧,这既要靠同步。当调用foo()时,会在(this)上获得一个锁。会禁止在被foo调用时执行相同的操作(从而导致死锁),还是会意识到锁已经被同一个线程获取?

希望我的解释是多还是不太清楚;-)

+0

为什么你对此做同步?你班上还有其他方法吗?您可以在方法上使用synchornized作为关键字。 –

+0

科林,我创建了一个内部处理缓存项目过期的缓存,通过使用两个映射,一个用于数据,另一个用于相应的过期时间戳。因此,既不用同步方法也不用同步地图就可以完成这项工作,因为这两个地图都是由许多方法操纵的,并且需要随时同步。 – usimon

回答

10

的​​块折返(事实上,Java监视折返,要非常清楚),因此没有死锁在您的情况发生。

根据the docs

回想一下,一个线程不能获取由另一个线程拥有的锁。 但是一个线程可以获得它已经拥有的锁。

3

如果线程持有对象的锁定,则它可以基于该锁定对象进入其他同步的块。

Here您可以阅读

” ......线程可以获取一个锁,它已经拥有。允许一个线程获得同样的锁不止一次使折返同步这描述的情况同步代码直接或间接地调用一个也包含同步代码的方法,并且这两组代码使用同一个锁。没有可重入同步,同步代码必须采取许多额外的预防措施以避免线程导致自身阻塞。 “

+0

感谢您的快速回答,这正是我需要知道的! – usimon

0

有一点要小心,虽然是如果:

Thread A has the lock in foo() and needs to call bar() 

and Thread B has the lock in bar() while needing to call foo() 
+0

我一般同意,但是当两个线程在同一个对象上同步时(这个)在这种情况下是不可能发生的 – usimon

+0

是的,我应该更清楚一点。我只是在描述一种会导致僵局的情况。 –