2012-06-25 144 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

是的,我應該更清楚一點。我只是在描述一種會導致僵局的情況。 –