2012-05-15 40 views
3

我有一個對象,它是not safe for multithreaded applications(以幾種方式),我想提供一個內部檢查以確保不會同時訪問關鍵方法。防禦反多線程類實現

問題

我應該採用什麼技術來檢測和防止多個線程訪問我的課?

跟蹤消費者可能使用的所有方法,屬性等的Thread.ID是否足夠?

+1

您將要完成的工作將會更好地使類類線程安全。也就是說,Brian的答案是正確的:只要記錄它不是線程安全的。 –

+1

我想知道更多關於什麼條件導致線程安全問題。有靜態的方法可以不可預測地進行交互嗎?你想阻止兩個不同的線程創建兩個實例嗎? – EtherDragon

+0

@EtherDragon - 完全。有幾個程度的線程安全性。 –

回答

2

它會幫助嗎?

lock(_padLock) 
{ 
    .... 
} 

或者如果你有你的對象外部訪問,你可以使用Mutex對象。

8

只是證明它不是線程安全的。這是.NET中類的慣例。

+0

如果消費者需要跨多個線程使用該對象,則可以確保其被正確訪問。 – Servy

+0

很高興被告知類是如何線程不安全的。如果每個線程創建一個單獨的實例或者一次只允許一個線程進行方法調用,則類可以正常工作。 –

+0

@MartinJames:對不起,我對你的評論有些困惑。如果你不是從多個線程訪問狀態,那麼類型是否線程安全並不重要。這種情況沒有問題。一次只允許一個線程是同步,這當然是使線程安全的一種方法。 –

0

檢查線程標識符會捕獲多線程的用途,因爲如果有人在多線程程序中使用它,它會拋出那些希望阻止人們使用該程序的消息。它不會很優雅,但它會最終提醒人們麻煩。如何使用該程序將確定在人們意識到錯誤之前所發生的嚴重損害的可能性。

但是一般來說,單線程代碼在多線程程序中工作得非常好。這是快速的(相對)易於編寫。 (當然,調用代碼必須是非常仔細)。您會放棄這個功能,並將其限制爲只能在程序中運行,以便在一個線程中運行它,從開始到程序結束。例如,在一個Windows桌面程序中,這意味着它必須在事件隊列中運行,這意味着它將在運行時綁定事件隊列 - 不需要工作線程!

大多數集合類都是單線程的,但在多線程程序中得到廣泛的使用。我將它們用作單線程編碼的模型。

0

屬性MethodImplOptions具有用於同步

指定該方法可以通過僅一個線程 時間執行枚舉。靜態方法鎖定類型,而實例方法鎖定實例上的 。只有一個線程可以在任何實例 函數中執行,並且只有一個線程可以在任何類的靜態函數中執行。

...雖然這是不建議。此方法的功能相當於lock(this),它允許其他類別意外或惡意佔用鎖定

另一個選項是使用單獨的對象用於鎖定。當這樣做時,它可以被標記爲只讀,除非它是像Spinlock這樣的結構。簡而言之:不要使用Spinlock的只讀屬性:這會導致每次調用SpinLock或_lock.Enter以獲取對象的新副本併成功。如果這樣做可能會造成腐敗。

class myClass 
    { 
     private object myLock;   //OK 
     private readonly object myLock2; //OK 
     private readonly SpinLock myLock3; //WARNING: Value type, won't work as intended 
     private SpinLock myLock4; //OK 

    void DoStuff() 
    { 
     lock(myLock4) 
     { 
      // some quick instructions... say 10 or fewer 
     } 
    } 
    } 
1

您可以使用的最佳內部檢查是其他人建議的lock設置。但是,這裏有一些值得研究的創造性方法,看看它們是否能解決您的具體問題。我遇到的問題是,我不知道是否只有類的部分是不安全的,如果線程安全的使用不同類的不同實例或不同類的線程。因此,這裏是減輕某些情況下

方案1的lock一些組合:靜態類/方法 - 這將確保無論是誰訪問靜態類/他們將被阻止會員如果另一個線程已經在這麼做了。

public static class UnsafeStaticClass 
{ 
    private static object _padLock = new object(); 

    public static void UnsafeStaticMethod() 
    { 
     lock(_padLock) 
     { 
      // Do Work 
     } 
    } 
} 

場景2:普通類,其中實例可以是並列的,但每個實例只允許有一個調用。多個實例可以同時運行代碼塊。

public class UnsafeClass 
{ 
    private object _padLock = new object(); 

    public void UnsafeMethod() 
    { 
     lock(_padLock) 
     { 
      // Do Work 
     } 
    } 
} 

方案3:一個類的實例,即與不安全靜態方法interracts - 因此需要以確保只有一個調用ouside靜態方法存在。無論有多少實例,只有其中一個可以一次運行該方法,因爲它鎖定了一個靜態對象。

public void UnsafeClass 
{ 
    private static object _padLock = new object(); 

    public void UnsafeInstanceMethod() 
    { 
     lock(_padlock) 
     { 
      // Do Work 
     } 
    } 
}   
+0

+1用於思考各種鎖定方案和源代碼 – LamonteCristo