2011-03-14 194 views
7

假設我在某個線程內部和​​塊內執行​​塊代碼,我調用一個方法來產生另一個線程來處理需要與第一個方法相同的鎖的同步代碼塊。因此,在僞Java代碼:Java線程和同步塊

public void someMethod() { 
    synchronized(lock_obj) { 
    // a whole bunch of stuff... 

    // this is the last statement in the block 
    (new Thread(someOtherMethod())).start(); 
    } 
    // some more code that doesn't require a lock 
} 

public void someOtherMethod() { 
    // some setup code that doesn't require a lock 

    // return the stuff we want to run in another thread 
    // that does require a lock 
    return new Runnable() { 
    @Override 
    public void run() { 
     synchronized(lock_obj) { 
     // some more code 
     } 
    } 
    }; 
} 

我不知道如何理解該代碼。我寫的甚至是合法的嗎?在句法上我沒有看到任何問題,但我不確定如何通過類似的代碼進行推理。因此,當我執行someOtherMethod()以創建Runnable的實例時,return語句之前的代碼在哪種範圍內運行?它是否作爲第一個同步塊的一部分執行?假設還有一些其他線程也可能需要鎖定lock_obj

回答

8

在創建runnable和線程期間,您仍然保持鎖定狀態,但在調用start之後,線程實際啓動之前,您將放棄鎖定。新線程必須與其他線程競爭鎖定。

5

這段代碼沒有錯。在someOtherMethod()中的return語句之前,代碼在someMethod()的同步塊中運行。新線程啓動後,將在run()方法內的​​語句上阻塞,直到它獲得lock_obj(最早,每當someMethod()退出其同步塊時)的鎖定。

+0

只是添加一些可能會丟失的內容 - 調用start()後,會立即退出someMethod()中的同步塊,並且新線程並行執行。這似乎是導致OP的困惑的原因。 – 2015-07-01 22:28:20

+0

@AbrahamPhilip - 我不會那樣說的。調用'start()'時,同步塊不會退出。 (它會在很短的時間後退出,因爲調用'start()'恰好是同步塊中的最後一條語句。)而是調用'start()'啓動另一個線程的執行(以無監視器開始持有),運行'someOtherMethod()'返回的'Runnable'中的代碼。該另一個線程需要等待'someMethod()'中的塊退出才能輸入它自己的同步塊。 – 2015-07-01 23:21:34

+0

對不起,你是對的。讓我改述一下,「剛剛調用start()之後」。我只是想強調一下,因爲OP在懷疑第二個線程的runnable是否在第一個synchronized塊中執行(這裏的答案是錯誤地聲稱http://stackoverflow.com/a/5295252/3000919)。我相信你的評論解釋得非常好,謝謝:) – 2015-07-01 23:41:55

-2

如果首先調用someMethod(),那麼它就是經典的死鎖例子。

我寫的甚至是合法的嗎?
----是的,它在句法上完全合法。

因此,當我執行someOtherMethod()以創建Runnable的實例時,返回語句運行之前的代碼的類型是什麼? ----如果someOtherMethod()從someMethod()中調用,那麼它在someMethod()方法的synchronized塊的作用域內。

+1

爲什麼它是一個僵局? Thread.start立即返回,此時釋放lock_obj上的鎖定,此時返回的Runnable會啓動該鎖定或等待其他某個線程釋放該鎖定。 – davidk01 2011-03-14 06:08:12

+1

同意@ davidk01這不是一個僵局。如果是的話,它當然不是「經典」的例子。只是爲了得到更多的信息,即使沒有線程啓動,調用java中的方法也是不會阻塞的,因爲調用方已經擁有該鎖。 – Sogger 2012-10-04 14:47:11