- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
"ConcurrentBag(T) is a thread-safe bag implementation, optimized for scenarios where the same thread will be both producing and consuming data stored in the bag." - MSDN
我有这个确切的用例(多个线程同时消费和生产),但我需要能够及时有效地确定袋子何时永久变空(我的线程只根据消费的东西生产,而包在线程启动之前用单个元素快速启动)。
我很难找到一种没有全局锁的无竞争条件的有效方法来执行此操作。我相信引入全局锁会抵消使用大部分无锁 ConcurrentBag 的好处。
我的实际用例是“无序”(二进制)树遍历。我只需要访问每个节点,并为每个节点做一些非常简单的计算。我不关心访问它们的顺序。当所有节点都被访问时,算法应该终止。
int taskCount = Environment.ProcessorCount;
Task[] tasks = new Task[taskCount];
var bag = new ConcurrentBag<TreeNode>();
bag.Add(root);
for (int i = 0; i < taskCount; i++)
{
int threadId = i;
tasks[threadId] = new Task(() =>
{
while(???) // Putting bag.IsEmpty>0 here would be obviously wrong as some other thread could have removed the last node but not yet added the node's "children"
{
TreeNode node;
bool success = bag.TryTake(out node);
if (!success) continue; //This spinning is probably not very clever here, but I don't really mind it.
// Placeholder: Do stuff with node
if (node.Left != null) bag.Add(node.Left);
if (node.Right != null) bag.Add(node.Right);
}
});
tasks[threadId].Start();
}
Task.WaitAll(tasks);
那么如何为此添加一个有效的终止条件?我不介意当袋子快要变空时条件变得昂贵。
最佳答案
我以前遇到过这个问题。在检查队列之前,我让线程注册为处于等待状态。如果队列为空并且所有其他线程也在等待,我们就完成了。如果其他线程仍然很忙,那么黑客来了,休眠 10ms。我相信通过使用某种同步(可能是 Barrier
)无需等待就可以解决这个问题。
代码是这样的:
string Dequeue()
{
Interlocked.Increment(ref threadCountWaiting);
try
{
while (true)
{
string result = queue.TryDequeue();
if (result != null)
return result;
if (cancellationToken.IsCancellationRequested || threadCountWaiting == pendingThreadCount)
{
Interlocked.Decrement(ref pendingThreadCount);
return null;
}
Thread.Sleep(10);
}
}
finally
{
Interlocked.Decrement(ref threadCountWaiting);
}
}
用 Barrier
替换 sleep 和计数器维护是可能的。我只是没有打扰,这已经够复杂了。
Interlocked
操作是可伸缩性瓶颈,因为它们基本上是使用硬件自旋锁实现的。所以你可能想在方法的开头插入一个快速路径:
string result = queue.TryDequeue();
if (result != null)
return result;
大多数情况下,将采用快速路径。
关于c# - ConcurrentBag 的预期用途和空作为终止条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34110123/
我一直在阅读新的并发集合,特别是 ConcurrentBag 引起了我的注意。由于 ConcurrentBag 内部在每个单独的线程上持有一个本地集,使用它来跟踪项目,这意味着当线程本身超出范围时,它
"ConcurrentBag(T) is a thread-safe bag implementation, optimized for scenarios where the same thread
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Possible memoryleak in ConcurrentBag? 我的应用中出现严重内存泄漏。我使
我正在运行一些使用 ConcurrentBags 的代码。我正在探索 IEnumerable 功能。我运行的代码是 ConcurrentBag bag = new ConcurrentBag(); T
.NET 4.5.1 我有一个包含 200,000 个对象的 ConcurrentBag。一个对象被两个 long 类型的属性认为是“唯一的”。 我需要检查包中是否存在以前存在的唯一对象,如果不存在,
我有一个 .NET 4.5 单实例 WCF 服务,它维护列表中的项目集合,该列表将同时具有并发的读者和作者,但读者比作者多得多。 我目前正在决定是否使用 BCL ConcurrentBag或使用我自己
有没有办法一次将多个项目添加到 ConcurrentBag,而不是一次添加一个?我没有在 ConcurrentBag 上看到 AddRange() 方法,但是有一个 Concat()。但是,这对我不起
我已经在这里阅读了之前关于 ConcurrentBag 的问题但没有找到在多线程中的实际实现示例。 ConcurrentBag is a thread-safe bag implementation,
分析后,我发现我的应用程序中的特定对象将通过使用对象池而不是构造对象池而受益匪浅。此应用程序基于具有多个线程的生产者/消费者队列。 ConcurrentBag 集合基本上是一个对象池,作为应用程序对象
我在使用包含非托管对象的 ConcurrentBag 正确处理 Dispose/Finalization 时遇到问题。运行下面的代码(通常)会在对 TryTake(). 大概在这种情况下,垃圾收集器在
我需要将 ConcurrentBag 设置为可通知的。我需要知道它安全吗?该类的代码是 public class NotifiableConcurrentBag : ConcurrentBag, IN
我有一个静态集合,比如调用远程 rest api 的任务: static ConcurrentBag> _collection = new ConcurrentBag>(); static void
我读到要修改或改变并发包中的对象,我必须将其取出、修改,然后再放回去。 但是,我看到了执行以下操作的代码: var obj = bag.FirstOrDefault(report => report.
当线程添加或删除 ConcurrentBag 的元素时会发生什么而另一个线程正在枚举这个包?新元素是否也会出现在枚举中,删除的元素是否不会出现? 最佳答案 一 jar read the fine ma
我编写了一个程序,其中列表构建器方法返回 IEnumerable of string,其中包括大量字符串(100 万个项目),我将其存储在 List of string 中,然后它将所有项目附加到 中
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Possible memoryleak in ConcurrentBag? 编辑1: 真正的问题是。你能证实
我已经构建了这段代码来并行处理大量字符串之间的字符串比较,以加快速度。 我使用了 ConcurrentBag,因此所有线程(任务)都可以写入线程安全集合。然后我将这个集合转储到一个文件中。 我遇到的问
我有一个应用程序,它有一个存储在 static ConcurrentBag 中的对象列表。 UI 有一个计时器,它运行的方法可以更新 ConcurrentBag 中的对象。 只有一个线程(由计时器启动
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T
如何清除ConcurrentBag?它没有任何方法,如 Clear 或 RemoveAll... 最佳答案 2017 年 10 月 3 日更新:正如@Lou 正确指出的那样,赋值是原子的。在这种情况下
我是一名优秀的程序员,十分优秀!