2015-03-02 82 views
1

我需要創建一個通用隊列,可以排隊我的多個生產者,並由多個消費者出隊。線程安全隊列<t>在C#

我希望系統至少在系統更改期間嘗試兩次操作,所以如果進程線程失敗,現在標記的qBit會再次排隊,然後再次處理時,執行該操作的線程會知道另一個線程已經嘗試過這個操作一次,如果失敗了,請將這個特定的一個發送到修復隊列以供外部干預。

所以....對於實際問題,我意識到隊列的狀態可能會在contains()和隊列操作之間改變,就像套接字檢查只是錯誤控制的一種形式,而不是替代。我這樣做是因爲兩個生產者線程可能會拋出一個錯誤,當兩個相同的id(由GUID標識)試圖排隊什麼,否則將是qBit的不同對象實例。

問題是,這是一個合理的實現?我不能看到它永遠陷入僵局,因爲所有的方法都會返回,無論處理qBit的結果如何,這可以讓我在某種程度上防止其中一些。

想法和/或第二組眼睛嗎?

public class tsQueue<t> 
{ 
    object syncLock = new object(); 
    private Queue<qBit<t>> Q = new Queue<qBit<t>>(); 
    List<t> contents = new List<t>(); 

    public qBit<t> deQueue() 
    { 
     lock (syncLock) 
     { 
      qBit<t> pop = Q.Dequeue(); 
      contents.Remove(pop.item); 
      return pop; 
     } 
    } 

    public void enQueue(qBit<t> push) 
    { 
     lock (syncLock) 
     { 
      contents.Add(push.item); 
      Q.Enqueue(push); 
     } 
    } 

    public bool contains(t check) { 
     lock (syncLock) 
     { 
      return contents.Contains(check); 
     } 
    } 

    public class qBit<t> 
    { 
     public bool flag { get; set; } 
     private t _item; 
     public t item { get { return _item; } } 

     public qBit(t item) 
     { 
      this._item = item; 
     } 
    } 
} 
+5

你看過'ConcurrentQueue '嗎? – phoog 2015-03-02 21:13:57

+1

這看起來線程安全給我。 @phoog我想用這兩種方法對解決方案進行基準測試。根據我的經驗,有時手動鎖定非線程安全對象實際上比使用線程安全的對象(即使用Queue vs ConcurrentQueue)更快。但是,我認爲使用這兩者之間的選擇必須是特定於應用程序的。 – phishfordead 2015-03-02 21:17:50

+0

@phishfordead如果性能是一個問題,是的,應該基準和考慮哪種解決方案更快。圖書館解決方案通常比手動解決方案慢;圖書館需要邏輯來處理可能與所討論的用例無關的條件。但是,庫代碼也可能比手動代碼更好地測試,更不用說更徹底的思考了。因此,應該將衡量更好性能的好處(如果實際上基準測試表現出更好的性能)與測試和調試的成本進行權衡,以確保正確性。 – phoog 2015-03-02 21:22:44

回答

0

ConcurrentQueue是一個線程安全的實現,它完全符合您的需求。你自己的代碼肯定會更快。使用這個link來查看ConcurrentQueue實現的源代碼。

+0

我看了一下ConcurrentQueue ,我有一些關於它的問題,在這裏引用https://msdn.microsoft.com/en-us/library/dd997373%28v=vs.110%29.aspx它使我不那麼所以我正在拍攝一個可能更長的手部方法,但更容易被窺視。我不認爲性能會成爲一個問題,它不是性能極高的表現,而必須毫無疑問是可靠的。 – Sabre 2015-03-02 22:19:07