我正在尝试实现最小的线程安全阻塞队列, 我想出的是:
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)”命令之间会发生什么事情?
答案 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();
}
}
}