2010-05-20 67 views
8

我有一種情況,只有在兩個鎖定對象空閒時才應該執行代碼塊。如何在C中使用多個變量鎖定範圍#

我希望會有這樣的:

lock(a,b) 
{ 
    // this scope is in critical region 
} 

然而,似乎一點也不像。所以這是否意味着做到這一點的唯一方法是:

lock(a) 
{ 
    lock(b) 
    { 
     // this scope is in critical region 
    } 
} 

這是否會按預期工作?雖然代碼編譯,但我不知道它是否會達到我期待的目標。

+0

這不會造成鎖定問題嗎?比如說一個對象鎖定了一個,而另一個鎖定了一個,現在你會有一個死鎖,其中object1阻塞了等待b和object2阻止b等待a。我不太熟悉鎖,但這看起來很糟糕。 – Tester101 2010-05-20 13:22:41

+2

這就是爲什麼鎖定順序很重要,因爲迄今爲止所有的答案都提到過。有時你需要有多個鎖,在這種情況下,要使用的一種標準模式是(至少通過約定)強制執行鎖。例如,你會說任何時候你想要獲得鎖,你必須首先獲得一個鎖。導致更多的爭用,但可以防止死鎖。 儘可能地避免這種事情總是更好,但有時候這是必要的。 – Herms 2010-05-20 13:26:07

+0

@ Tester101:是的,我知道如果處理不當,會導致死鎖。 – 2010-05-20 13:52:55

回答

5

我期待它,雖然會有可能導致死鎖情況的情況。

通常情況下,代碼將嘗試鎖定a,如果成功,則繼續鎖定b。這意味着它只會執行代碼,如果它可以鎖定ab。這是你想要的。

但是,如果其他代碼已經鎖定了b,那麼此代碼將不會達到您的預期。您還需要確保無論您需要鎖定a還是b,都會嘗試按相同順序獲取鎖。如果先獲得b,然後再獲得a,則會導致死鎖。

+0

其實它不會失敗,如果別的東西有鎖在b - 它會等到它被釋放。 – TomTom 2010-05-20 13:22:32

+1

@TomTom:如果另一個線程只是試圖訪問其中一個鎖,那麼我們不會有任何問題,但是如果它試圖鎖定a和b並以相反順序鎖定,則很有可能發生死鎖。 @ChrisF:你在編輯時是否需要外部花括號,或者你只是爲了讓代碼看起來更清潔? – 2010-05-20 14:04:26

+0

@Gunner - 只是試圖讓代碼看起來更清晰並明確鎖定的範圍。希望沒關係。 – ChrisF 2010-05-20 14:20:46

11

在兩者上請求鎖應該工作正常。 lock(a)將阻止,直到a是免費的。一旦你有這個鎖,lock(b)將阻止,直到你有b。之後,你有兩個。

你需要非常小心的一件事是順序。如果你打算這樣做,請確保你總是獲得a上的鎖之前獲得鎖b。否則,你可能很容易發現自己陷入僵局。

15
lock(a) lock(b) { // this scope is in critical region } 

這可能會阻止,直到線程可以獲取鎖a。然後,在獲得該鎖的情況下,該線程將阻塞,直到線程可以獲取b的鎖。所以這個按預期工作。

但是,你必須要小心,不要做別的地方:

lock(b) lock(a) { // this scope is in critical region } 

這可能導致在線程1獲取鎖定爲a,並正在等待獲取的鎖死鎖情況b,並且線程2已獲取鎖b並正在等待獲取鎖a