在什么情况下 TryDequeue 和类似的 System.Collections.Concurrent 收集方法会失败
我最近注意到 System.Collections.Concurrent 命名空间通常会看到 Collection.TrySomeAction()
而不是 Collection.SomeAction()
。
这是什么原因呢?我认为这与锁定有关?
所以我想知道在什么条件下尝试(例如)从堆栈、队列、包等中出列项目会失败?
I have recently noticed that inside the collection objects contained in System.Collections.Concurrent namespace it is common to see Collection.TrySomeAction()
rather then Collection.SomeAction()
.
What is the cause of this? I assume it has something to do with locking?
So I am wondering under what conditions could an attempt to (for example) Dequeue an item from a stack, queue, bag etc.. fail?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
System.Collections.Concurrent 命名空间中的集合被认为是线程安全的,因此可以使用它们编写在线程之间共享数据的多线程程序。
在 .NET 4 之前,如果多个线程可能访问单个共享集合,则必须提供自己的同步机制。每次修改集合的元素时都必须锁定该集合。您可能还需要在每次访问(或枚举)集合时锁定该集合。这是最简单的多线程场景。某些应用程序会创建后台线程,随着时间的推移将结果传递到共享集合。另一个线程将读取并处理这些结果。您需要在线程之间实现自己的消息传递方案,以便在新结果可用以及这些新结果已被使用时相互通知。 System.Collections.Concurrent 中的类和接口为这些问题和其他涉及以无锁方式跨线程共享数据的常见多线程编程问题提供了一致的实现。
Try
具有语义 - try 执行该操作并返回操作结果。DoThat
语义通常使用异常抛出机制来指示可能效率不高的错误。例如,它们可以返回 false,ConcurentDictionary
中拥有它;尝试阅读:
Collections in
System.Collections.Concurrent
namespace are considered to be thread-safe, so it is possible to use them to write multi-threaded programs that share data between threads.Before .NET 4, you had to provide your own synchronization mechanisms if multiple threads might be accessing a single shared collection. You had to lock the collection each time you modified its elements. You also might need to lock the collection each time you accessed (or enumerated) it. That’s for the simplest of multi-threaded scenarios. Some applications would create background threads that delivered results to a shared collection over time. Another thread would read and process those results. You needed to implement your own message passing scheme between threads to notify each other when new results were available, and when those new results had been consumed. The classes and interfaces in
System.Collections.Concurrent
provide a consistent implementation for those and other common multi-threaded programming problems involving shared data across threads in lock-free way.Try<something>
has semantics - try to do that action and return operation result.DoThat
semantics usually use exception thrown mechanics to indicate error which can be not efficient. As examples there they can return false,ConcurentDictionary
;Try to read:
失败是什么意思?
采取以下示例:
上面的代码抛出异常,因为我们尝试从空队列中出队。现在,如果您改用
ConcurrentQueue
:上面的代码将不会引发异常。队列仍然无法使项目出队,但代码不会以抛出异常的方式失败。其真正用途在多线程环境中变得显而易见。非并发
Queue
的代码通常如下所示:为了避免竞争条件,我们需要使用锁来确保队列在过去的时间内不会发生任何情况通过检查
Count
来调用Dequeue
。使用ConcurrentQueue
,我们实际上不需要检查Count
,而是可以调用TryDequeue
。如果您检查在
Systems.Collections.Concurrent
命名空间中找到的类型,您会发现其中许多包装了两个通常按顺序调用的操作,并且传统上需要锁定(Count 后跟
ConcurrentQueue
中的Dequeue
、ConcurrentDictionary
中的GetOrAdd
替换序列调用ContainsKey
、添加项目并获取它,等等)。What do you mean with fail?
Take the following example:
The above code with throw an exception, since we try to dequeue from an empty queue. Now, if you use a
ConcurrentQueue<T>
instead:The above code will not throw an exception. The queue will still fail to dequeue an item, but the code will not fail in the way of throwing an exception. The real use for this becomes apparent in a multithreaded environment. Code for the non-concurrent
Queue<T>
would typically look something like this:In order to avoid race conditions, we need to use a lock to ensure that nothing happens with the queue in the time that passes from checking
Count
do callingDequeue
. WithConcurrentQueue<T>
, we don't really need to checkCount
, but can instead callTryDequeue
.If you examine the types found in the
Systems.Collections.Concurrent
namespace you will find that many of them wrap two operations that are typically called sequentially, and that would traditionally require locking (Count
followed byDequeue
inConcurrentQueue<T>
,GetOrAdd
inConcurrentDictionary<TKey, TValue>
replaces sequences of callingContainsKey
, adding an item and getting it, and so on).例如,如果没有任何内容需要“出列”...这种“Try-Pattern”在 FCL 和 BCL 元素中普遍使用。这与锁定无关,并发集合(或至少应该)大部分是在没有锁的情况下实现的......
If there is nothing to be "dequeued", for example... This "Try-Pattern" is used commonly all across FCL and BCL elements. That has nothing to do with locking, concurrent collections are (or at least should be) mostly implemented without locks...