2011-01-25 56 views
3

我正在分析大量的多線程代碼,我看到了這麼多的鎖。一些方法將有兩個鎖在這樣的一行:同步代碼味道?

ClassA::foo() 
{ 
    lockA.lock(); 
    lockB.lock(); 

    ...//do some stuff 

    lockB.unlock(); 
    lockA.unlock(); 
} 

我的問題是很一般(我不能提供實際的代碼)。這是代碼味道嗎?這通常是不好的做法?我無法證明代碼可以被簡化,但它看起來好像它是否被正確編碼,不需要鎖定兩件事。鎖應該管理一組需要同步的資源,對吧?如果有兩個鎖與資源管理重疊,那麼是否會出現一些死鎖問題?

如果您有任何見解,請讓我知道。

感謝, JBU

回答

2

這是很常見的一段代碼到需要採取兩把鎖,讓本身並不代表一個代碼味道。如果這些鎖是總是放在一起,這將是一個問題,他們可能應該合併。但是,如果有其他地方的鎖是分開拍攝的,那麼這種模式很好。

我會在您的代碼片段中評論的唯一一件事情是,您最好使用RAII鎖類,以使您的代碼異常安全並避免其他類型的代碼錯誤(例如意外不會釋放鎖定一些代碼路徑)。

+0

如果另一個線程的方法確實是這樣ClassB的::巴(){lockB.lock();洛卡。鎖();做東西; lockA.unlock(); lockB.unlock();}(注意鎖定順序的逆轉)那麼存在死鎖的條件是不是?也許要添加到您的答案,鎖定需要按照一致的順序完成? – jbu 2011-01-25 16:24:50

+0

是的,鎖定需要按照一致的順序進行。 – 2011-01-25 16:27:55

3

這可能是一種氣味,它可能不是,取決於上下文和項目範圍。如果你發現自己弄了5個鎖來同步排隊的列表,那麼你可能做錯了什麼。通常我想在共享資源和鎖之間有一個很好的比例。

有時它可能會誘惑鎖定更細密的級別(即對列表中的每個項目使用鎖而不是整個列表的鎖)。重新激發這種衝動,直到一名探查者告訴你這把鎖很滿足。

通過使用不鎖定鎖來保護單個資源,但保護商業邏輯的某些部分,您應該可以將多個鎖組合成一個鎖,以防止爭用。你可能會失去一點點的表現,但是如果你能擺脫10個鎖,它通常會爲它帶來的簡單性而付出代價。

我想你的問題的答案是在一個問題的形式:爲什麼你的classA同時使用兩個共享資源?通常這是我在設計階段嘗試避免使用某種單一責任原則。通常,共享資源屬於某人,並且某人是鎖定/解鎖資源的單一權限。

有沒有什麼可以重構的方法來任何方式:

lockA.lock(); 
//some code 
lockA.unlock(); 
lockB.lock(); 
//some other code 
lockB.unlock(); 

一個明確的事情,以確保:應該有訂貨鎖(即洛卡> LOCKB)的預定有限/定義的方式,只鎖他們按升序排列。

你不應該得到的

lockA.lock(); 
lockB.lock(); 

的情況和一些其他的代碼

lockB.lock(); 
lockA.lock();