2014-12-04 55 views
0

如下面的示例所示,一旦對call方法中的對象執行了鎖定,則不需要其他方法來使用​​關鍵字。多級java行爲同步

public class Prac 
{ 
    public static void main(String[] args) 
    { 
     new Prac().call(); 
    } 

    private synchronized void call() 
    { 
     further(); 
    } 

    private synchronized void further() 
    { 
     oneMore(); 
    } 

    private synchronized void oneMore() 
    { 
     // do something 
    } 
} 

但是,如果我還添加​​關鍵字furtheronceMore,這樣的遭遇做什麼java嗎? java是否檢查是否需要鎖定?或者當方法調用位於同一堆棧中時,它只是繼續執行,而不檢查是否需要鎖定,因爲鎖定已經獲取。

注意:我懷疑java是如何在這種情況下行爲的,我不確定,但我認爲它與偏向鎖定不同。

回答

4

事實上,java會在每次進入同步方法時檢查當前線程是否有鎖。

private synchronized void oneMore() 
    { 
     // do something 
    } 

這相當於

private void oneMore(){ 
     synchronized(this){ 
     // do something 
    } 
} 

但是因爲事實上,在Java中的內在鎖是可重入的;如果一個線程擁有鎖定,那麼一旦它進入另一個同步塊,就不會重新獲取它,如同你的例子。否則,這會造成死鎖。

更新:在下面回答您的評論。從Java併發性實踐:

Reentrancy is implemented by associating with each lock an acquisition count 
and an owning thread. When the count is zero, the lock is considered unheld. 
When a thread acquires a previously unheld lock, the JVM records the owner 
and sets the acquisition count to one. If that same thread acquires the lock 
again, the count is incremented, and when the owning thread exits the 
synchronized block, the count is decremented. When the count reaches zero, 
the lock is released. 

因此,檢查是否鎖被收購,相當於一個if語句(或多或少),該變量保存擁有線程等於或不線程試圖收購鎖。

但是,正如您所指出的那樣,private方法中不需要synchronized關鍵字。一般來說,您應該嘗試刪除不必要的同步,因爲這通常會導致性能下降。

+0

檢查鎖是否會增加任何性能開銷? – Batty 2014-12-04 09:35:46