2015-03-02 38 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