这个 BlockingQueue 线程安全吗?

Is this BlockingQueue Thread safe?

我正在尝试自己实现一个最小的线程安全阻塞队列, 我想到的是:

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)" 命令之间发生了什么?

是的,它可能会发生... Thread.Abort() 会打断这个队列。

semaPhore.Wait();

// Here a Thread.Abort() happens

lock(myQueue) ...

然后发生的事情是队列中有一个元素无法恢复,因为 "free" 信号量插槽比队列项少一个。

除此之外(还有 .NET 4.0 专家编写的 BlockingCollection<> 事实),我会说代码是正确的。 semaPhore.Release() 造成隐式屏障(因为它内部使用了一个lock),所以内存中的写入顺序没有问题(首先Enqueue() 将是really 完成,则 Release() 将完成)。请注意,它会表现不佳,因为每个操作都需要两个 lock(你的加上 SemaphoreSlim 中的一个)。

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

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();
        }
    }
}