简体   繁体   English

Queue.Peek线程安全吗?

[英]Is Queue.Peek thread safe?

A read operation on a 32 bit field is atomic. 对32位字段的读取操作是原子的。 So if the queue holds object references the Queue.Peek method should be thread safe, right? 因此,如果队列中包含对象引用,则Queue.Peek方法应该是线程安全的,对吗?

No. And even if it were, that misses the point. 不。即使是这样,也没有抓住重点。 Let's assume a thread-safe peek for a moment. 让我们假设一下线程安全的偷看。 You typically end up writing code that does something kind of like this: 通常,您最终会编写执行如下操作的代码:

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

That's a bug in multi-threaded code even if Peek() and Dequeue() are themselves both thread-safe, because you need to remember that the queue can change in between when you check with Peek() and when you act on the information it gives you with Dequeue(). 即使Peek()Dequeue()本身都是线程安全的,这也是多线程代码中的一个错误,因为您需要记住,在使用Peek()检查和对信息进行操作之间,队列可以在两者之间进行更改。它为您提供Dequeue()。 You need to make sure you lock around both parts. 您需要确保锁定两个部分。

No, you should still lock around each Peek() call. 不,您仍然应该锁定每个Peek()调用。

Since Queue internally uses an Array, its instance methods are not thread safe, because array could be changed by a different thread at any time. 由于Queue在内部使用Array,因此其实例方法不是线程安全的,因为array可以随时由其他线程更改。

Peek() also checks for queue length to see if there are elements in the queue before returning the actual value, and some other thread might remove those elements before the method actually returns those values. Peek()还检查队列长度,以在返回实际值之前查看队列中是否有元素,并且其他一些线程可能会在方法实际返回那些值之前删除这些元素。

If you look at the implementation in .net reflector, it looks like this... 如果您查看.net反射器中的实现,则看起来像这样...

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

So no. 所以不行。 Not thread safe. 不是线程安全的。

It is not thread safe. 它不是线程安全的。

But to synchronize it you may find a ReaderWriterLockSlim to be the best. 但是要进行同步,您可能会发现ReaderWriterLockSlim是最好的。 Only the Enqueue() and Dequeue() methods would require a write-lock. 只有Enqueue()Dequeue()方法需要写锁定。 Peek() would only require a read-lock. Peek()仅需要读取锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM