2011-05-24 42 views
15

好吧,我已經使用了相當多的鎖,但是我從未有過這種情況。我有包含用於修改相同MSACCESS數據庫代碼兩個不同的類:爲什麼鎖定一個公共對象是一個壞主意

public class DatabaseNinja 
{ 
    public void UseSQLKatana 
    { 
     //Code to execute queries against db.TableAwesome 
    } 
} 

public class DatabasePirate 
{ 
    public void UseSQLCutlass 
    { 
     //Code to execute queries against db.TableAwesome 
    } 
} 

這是一個問題,因爲事務數據庫不能並行地執行,並且這些方法(UseSQLKatana和UseSQLCutlass)由稱爲不同的線程。

在我的研究中,我看到它是使用公共對象作爲鎖對象的不良做法因此,如何鎖定這些方法以避免它們串聯運行?答案僅僅是讓這些方法在同一個類中? (在我的真實代碼中實際上並不那麼簡單)

+1

我猜db.TableAwesom是一個公共表。你能創建一個訪問這個表的公共方法,並使用你的私有鎖嗎? – jp2code 2011-05-24 14:55:44

回答

15

嗯,首先,你可以創建一個三等:

internal class ImplementationDetail 
{ 
    private static readonly object lockme = new object(); 
    public static void DoDatabaseQuery(whatever) 
    { 
     lock(lockme) 
      ReallyDoQuery(whatever); 
    } 
} 

現在UseSQLKatana和UseSQLCutlass調用ImplementationDetail.DoDatabaseQuery。

其次,您可以決定不用擔心它,並鎖定兩種類型都可見的對象。避免這種情況的主要原因是因爲很難推斷誰在鎖定對象,並且難以防範惡意的部分可信代碼鎖定對象。如果你不關心這兩方面的缺點,那麼你就不必盲目遵循指南。

+0

我只是建議第三類方法,但我的打字速度並不快。 :P – 2011-05-24 14:58:12

+0

謝謝,Eric,這些都是好想法。爲了遵循以下規則,讓我們不要遵守規則。 =) – 2011-05-24 14:58:45

+0

我認爲,如果想簡單地調試死鎖問題,那麼公共互斥可能會有所幫助,但它比起公共鎖對象不太可能首先引起問題 - 您仍然可以其他代碼鎖定,導致問題。我看到的唯一解決方案是將訪問資源的實例減少到方法(或者至少是一個類)並將其鎖定在該方法上;無論是在那裏使用互斥鎖還是一個對象似乎都不相關。感謝大家!!! – 2011-05-24 15:47:56

2

使用Mutex
您可以在主類中創建互斥並在每個類的開頭調用Wait方法(方法);然後設置互斥,所以當另一個方法被調用時,它會等待頭等艙完成。
啊,請記住釋放這些方法退出互斥...

+2

如何鎖定公共互斥鎖比鎖定公共對象更好(或更糟糕)? – 2011-05-24 14:57:06

+0

@Eric:我也建議'Mutex',我認爲這是因爲我們可以'等待'它使我們可以控制流而不是直接破壞,​​或者我們可以在'TryEnter'和''''''''''''''最終獲得一個'國家',我猜想會有所幫助 - 我認爲,否則你考慮?只是問,因爲如果是的話,我會刪除我的壞回答。 – 2011-05-24 15:01:29

+0

@Mr。失望:讓我澄清;我不打算批評馬可的答案;而是一個誠實的問題。讀過這個答案的人可能會感到困惑:如果你可以使用鎖或使用互斥鎖,那麼每個人有什麼優點和缺點? – 2011-05-24 15:04:31

8

鎖定公共對象的壞習慣的原因是,你永遠不能確定誰是ELSE鎖定該對象。雖然不太可能,但是有一天某個人可以決定他們想要抓住你的鎖對象,然後做一些最終調用你的代碼的過程,在那裏鎖定同一個鎖對象,現在你有一個不可能的死鎖找出來。 (這是使用'this'的相同問題)。

更好的方法是使用公開的Mutex對象。這些重量更重,但調試問題要容易得多。

+0

謝謝你解釋爲什麼這是一個壞主意 - 我有點模糊在推理上。 =) – 2011-05-24 14:54:14

+2

這個答案也是這一點的一個很好的解釋:http://stackoverflow.com/questions/1873201/why-are-locks-performed-on-separate-objects – 2011-05-24 14:54:53

0

您可以使用公共LOCK對象作爲鎖定對象。你只需要指定你創建的對象是一個Lock對象,僅用於鎖定Ninja和Pirate類。

0

在這裏我看到兩個不同的問題:

爲什麼是一個壞主意,lock公共對象?

的想法是,鎖定的對象上,而lock保持限制訪問 - 這意味着沒有成員的可以被訪問,和其他來源可能不知道的lock的,並試圖利用例如,即使試圖自己獲得lock,因此造成問題。

因此,請使用專用對象實例鎖定。

如何鎖定這些方法以避免串聯運行?

你可以考慮Mutex類;創建一個'全局'互斥量將允許您的類在知道整個應用程序的鎖狀態的基礎上運行。或者,您可以使用共享的ReaderWriterLockSlim實例,但我不會推薦它的跨類共享。

+0

好的電話,這真的是兩個問題 - 我很欣賞你們倆的意見! – 2011-05-24 15:00:36

相關問題