Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 此BlockingQueue线程安全吗?_C#_Thread Safety_Blockingqueue - Fatal编程技术网

C# 此BlockingQueue线程安全吗?

C# 此BlockingQueue线程安全吗?,c#,thread-safety,blockingqueue,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) {

我试着实现一个最小的线程安全阻塞队列, 我想到的是:

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();
        }
    }
}
类阻塞队列
{
专用队列myQueue=新队列();
私有信号量slim信号量=新信号量slim(0);
公共无效排队(T)
{
锁(myQueue)
{
myQueue.Enqueue(t);
semaPhore.Release();
}
}
公共T出列()
{       
semaPhore.Wait();
锁(myQueue)
{
返回myQueue.Dequeue();
}
}
}
我试着对几个生产者和消费者同时进行压力测试,以随机的时间间隔排队,但没有失败


但是,如果我仔细查看代码,在“semaPhore.Wait()”和“lock(myQueue)”命令之间会发生什么事情吗?

是的,可能会发生。。。
Thread.Abort()
将中断此队列

semaPhore.Wait();

// Here a Thread.Abort() happens

lock(myQueue) ...
然后发生的情况是,队列中有一个元素没有人能够恢复,因为与队列项目相比,有一个更少的“空闲”信号量插槽


除此之外(还有一个由专家在.NET4.0中编写的
BlockingCollection
),我会说代码是正确的
semaPhore.Release()
会导致一个隐式障碍(因为它在内部使用了一个
),所以内存中的写入顺序没有问题(首先将真正完成
Enqueue()
,然后将完成
Release()
)。请注意,它将处于执行不良状态,因为每个操作需要两个
锁(您的加上
信号量lim
)中的一个。

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

类阻塞队列
{
专用队列myQueue=新队列();
公共无效排队(T)
{
锁(myQueue)
{
myQueue.Enqueue(t);
Monitor.Pulse(myQueue);
}
}
公共T出列()
{       
锁(myQueue)
{
Monitor.Wait(myQueue);
返回myQueue.Dequeue();
}
}
}

您是想学习如何编写
阻塞队列
,还是为了工作?因为在.NET 4.0中有一个
BlockingQueue
可能更合适?我投票将这个问题作为离题题来结束,因为它应该转移到CodeReview中。@AndreasNiedermair有一个具体的问题:但是,如果我仔细看代码,“semaPhore.Wait()”和“lock(myQueue)”之间会发生什么事情吗命令???@wonderb0lt OP怀疑代码中非常特定的部分可能无法按预期工作。这使得它脱离了代码审查的主题。正确,但Thread.Abort()会破坏很多东西。这很奇怪,我会明确地将其包含在这样一个队列的要求中。@HenkHolterman你说得很对。。。但是微软修改了<代码>监视器。只输入了<代码>线程。中止了<代码>(然后有趣地没有改变所有其他的同步对象……)所以如果我想考虑线程th.中止(),我应该走很长的路,类似于微软锁({)}。implementation@trykyn对您需要将
信号量lim
(它在内部使用
监视器.Pulse
…)与
队列
和监视器.Wait And.Pulse的处理进行“合并”。您不需要额外的同步对象。确定,当Enqueue()和Pulse()之间发生线程.Abort()时会发生什么情况?
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();
        }
    }
}