这个BlockingQueue线程安全吗
本文关键字:安全 线程 BlockingQueue 这个 | 更新日期: 2023-09-27 17:53:44
我正在尝试实现一个最小线程安全阻塞队列,我想到的是:
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.Wet(("answers"lock(myQueue("命令之间会发生什么事情吗?
是的,它可能发生。。。Thread.Abort()
会破坏此队列。
semaPhore.Wait();
// Here a Thread.Abort() happens
lock(myQueue) ...
然后发生的情况是,队列中有一个元素没有人能够恢复,因为"空闲"信号量槽比队列项目少一个。
除此之外(还有专家在.NET4.0中编写的BlockingCollection<>
(,我认为代码是正确的。semaPhore.Release()
会导致一个隐式屏障(因为它在内部使用lock
(,所以在内存中的写入顺序没有问题(首先Enqueue()
会被真正地完成,然后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();
}
}
}