这个BlockingQueue线程安全吗?

时间:2015-06-05 11:28:30

标签: c# thread-safety blockingqueue

我正在尝试实现最小的线程安全阻塞队列, 我想出的是:

class BlockingQueue<T>
{
    private Queue<T> myQueue = new Queue<T>();
    private SemaphoreSlim semaPhore = new SemaphoreSlim(0); 
    public void Enqueue(T t)
    {
        lock(myQueue)
        {
            myQueue.Enqueue(t);
            semaPhore.Release();
        }
    }
    public T Dequeue()
    {       
        semaPhore.Wait();
        lock(myQueue)
        {
            return myQueue.Dequeue();
        }
    }
}

我尝试对几个生产者和消费者进行压力测试,同时以随机的时间间隔排队/出队,并且没有失败。

但是,如果我批评一下代码,“semaPhore.Wait()”和“lock(myQueue)”命令之间会发生什么事情?

2 个答案:

答案 0 :(得分:2)

是的,可能会发生...... Thread.Abort()会破坏此队列。

semaPhore.Wait();

// Here a Thread.Abort() happens

lock(myQueue) ...

然后会发生的事情是队列中有一个元素没有人能够恢复,因为有一个元素少了#34; free&#34;信号量槽比队列项。

除此之外(以及.NET 4.0专家编写的BlockingCollection<>这一事实),我会说代码是正确的。 semaPhore.Release()导致隐式障碍(因为内部使用lock),因此内存中的写作顺序没有问题(首先Enqueue() em>完成,然后Release()将完成)。请注意,它的效果不佳,因为每项操作都需要两个lock(您的SemaphoreSlim加上div)。

答案 1 :(得分:-1)

使用我现在提出的建议,令人惊讶的是它使用更少的代码行:)

class BlockingQueue<T>
{
    private Queue<T> myQueue = new Queue<T>();

    public void Enqueue(T t)
    {
        lock(myQueue)
        {
            myQueue.Enqueue(t);
            Monitor.Pulse(myQueue);
        }
    }
    public T Dequeue()
    {       
        lock(myQueue)
        {
            Monitor.Wait(myQueue);
            return myQueue.Dequeue();
        }
    }
}