A座并发收集,如ConcurrentBag或BlockingCollection [英] Block a Concurrent Collection such as a ConcurrentBag or BlockingCollection

查看:159
本文介绍了A座并发收集,如ConcurrentBag或BlockingCollection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要执行两个语句访问 ConcurrentBag 无任何其他线程之间的访问入。例如:

I want to execute two statements accessing a ConcurrentBag without any other thread accessing it in between. For example:

ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();
concurrentBag.Add(1);
int check = 0;
//Somehow block so that the following two statements will 
//be executed without any other thread accessing concurrentBag.
concurrentBag.TryPeek(out check);
if (check == 2) concurrentBag.Add(3);

这怎么办呢?

how can that be done?

推荐答案

我怀疑这将是不仅仅是包装的code几行与锁定关键字。原因是,你将不得不换所有访问 ConcurrentBag 有锁。如果你这样做,那么它会不会是同步了。我想你问的是什么办法暂停,取而代之的是序列化的行为集合的并发行为,然后再次恢复并发的行为,当你完成一个特殊的守卫操作。

I suspect this is going to be significantly harder than just wrapping a few lines of code with the lock keyword. The reason being that you would have to wrap all access to the ConcurrentBag with a lock. And if you did that then it would not be "concurrent" anymore. I think what you are asking for is a way to temporarily suspend the concurrent behavior of the collection in favor of a serialized behavior and then resume its concurrent behavior once again when you have completed a special guarded operation.

天真的方法是建立自己的收藏,通过在内部使用它作为底层集合提供了相同的操作 ConcurrentBag 。然后,您可以提供 SuspendConcurrent ResumeConcurrent ,通过设置和重置一个标志切换集合的并发行为操作(可能通过 Interlocked.CompareExchange 法)。在code然后将使用此标志来确定是否直接转发添加 TryPeek TryTake 操作底层集合或在这样做之前使用硬锁。我认为到最后你会发现code非常复杂的,令人难以置信的很难得到正确。根据个人经验,任何简单的实现你预想,现在可能要么是错误的,是低效的,或当你想它是不是完全同步。

The naive approach would be to create your own collection that provides the same operations as ConcurrentBag by using it internally as the underlying collection. You would then provide SuspendConcurrent and ResumeConcurrent operations that toggle the concurrent behavior of the collection by setting and resetting a flag (probably via the Interlocked.CompareExchange method). The code would then use this flag to determine whether to directly forward Add, TryPeek, and TryTake operations to the underlying collection or use a hard lock before doing so. I think in the end you will find the code very complex and incredibly hard to get right. Based on personal experience any trivial implementation you are envisioning right now will probably either be wrong, be inefficient, or not be fully concurrent when you want it to be.

我的建议是找出一种方式来调整你的code,这样没有这一要求。

My advice is to figure out a way to restructure your code so that this requirement goes away.

编辑:

从您的意见之一,它好像你想要一个 CAS像操作,以便能够使基于是否不是已发生的决定。有几个选项,但其中一个可能最适合您的需要是使用 ConcurrentDictionary 类,它提供了 TryAdd 方法。 TryAdd 将返回true,如果该键不存在。如果密钥确实存在,那么它就会返回false。许多线程可同时执行该方法使用相同的密钥,但只有一个会得到真响应。然后,您可以使用如果语句根据返回值来控制程序流程。

From one of your comments it seems as though you want a CAS like operation to be able to make a decision based on whether or not something has already occurred. There are several options, but one which might best suit your needs is to use the ConcurrentDictionary class which provides the TryAdd method. TryAdd will return true if the key does not yet exist. If the key does exist then it will return false. Many threads can be executing this method simultaneously with the same key, but only one will get the true response. You can then use an if statement to control program flow based on the return value.

这篇关于A座并发收集,如ConcurrentBag或BlockingCollection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆