Queue.Peek线程安全吗?

时间:2009-10-12 12:44:40

标签: c# multithreading queue

对32位字段的读操作是原子的。因此,如果队列持有对象引用,Queue.Peek方法应该是线程安全的,对吗?

4 个答案:

答案 0 :(得分:18)

没有。即便如此,也忽略了这一点。让我们假设一个线程安全的窥视片刻。您通常最终会编写执行类似这样的代码:

if (MyQueue.Peek() != null)
  var item = MyQueue.Dequeue();

这是多线程代码中的一个错误,即使Peek()Dequeue()本身都是线程安全的,因为您需要记住,当您使用Peek()检查时,队列之间可以发生更改当你对信息采取行动时,它会给你Dequeue()。您需要确保锁定两个部分。

答案 1 :(得分:7)

不,你仍然应该锁定每个Peek()电话。

由于Queue内部使用一个Array,因此它的实例方法不是线程安全的,因为数组可以随时由另一个线程更改。

Peek()还检查队列长度,以便在返回实际值之前查看队列中是否有元素,而其他一些线程可能会在方法实际返回这些值之前删除这些元素。

答案 2 :(得分:4)

如果你看看.net反射器中的实现,它看起来像这样......

public virtual object Peek()
{
    if (this._size == 0)
    {
        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyQueue"));
    }
    return this._array[this._head];
}

所以没有。不是线程安全的。

答案 3 :(得分:2)

它不是线程安全的。

但要同步它,您可能会发现ReaderWriterLockSlim是最好的。只有Enqueue()Dequeue()方法才需要写锁定。 Peek()只需要一个读锁定。