5

假设一个 FIFO(一个线程安全的)有项目被添加到它(我们不在乎如何

|__|  |
|  |  |
|__|  |
|  |  |
|__|  V
| d|
|__|
| c|
|__|
| b|
|__|
| a|

现在让我们说项目(一个接一个)应该插入到 另一个并发集合中。

数据插入的速率是动态的。

我想以最快的方式做到这一点。(将所有元素从 转移Fifocollection)。

但我有一个冲突:

  • 我可以使用一根线从 中拉出物品Fifo并将它们插入collection. 但是我不会使用可以帮助我的核心/其他线程。

  • 我可以使用多个消费者线程从中获取项目Fifo,但是Fifo(读取时)上的内部锁定和collection(写入时)上的内部锁定最终会降低性能。

我的意思是,如果我有巨大的消费者线程,也会有巨大的内部锁定与先进先出/集合,再加上许多上下文切换。

我怎样才能以正确的方式解决这类问题?指导方针是什么?

4

4 回答 4

1

多个线程争夺同一个并发集合总是会成为瓶颈的情况。线程越多,问题通常会变得更糟,但退化的速度取决于锁定机制。我希望 .NET 4.0 中的新并发集合是无锁的,或者至少使用非阻塞锁,因此它们应该在一定程度上是争用友好的。

由于这个问题似乎是开放式的,我建议您简单地尝试不同数量的线程,并在 fifo 争用和您想要实现的吞吐量之间找到一个平衡点。

于 2013-01-09T07:28:22.000 回答
0

如果您在集合之间进行最少的处理,请仅使用一个线程。如果您有多个目标集合,那么您可能想要使用多个线程。或者,如果两端的数据结构是具有高级锁定的复杂结构,它实际上支持多线程插入,而不仅仅是锁定东西。

于 2013-01-09T07:32:31.833 回答
0

我会考虑为此使用任务并行库(TPL)。

您可以保留一个队列,当它有项目时,让并行框架为您完成所有繁重的工作。无需使用所有繁琐的代码管理线程来处理您自己的线程池。

必须承认我自己还没有这样做,但如果我处于你的情况,我会刷新我的 TPL 技能并开始考虑任务而不是线程 x。

于 2013-01-09T07:36:43.100 回答
0

如果我们可以访问两个集合的内部,这可以通过几个非交互线程来完成。例如,如果该堆栈是一个已知大小的链表,则两个线程可以从两端处理它直到它们相遇,并且它们可以构建一个新的链表,一个将元素附加到尾部,另一个附加到头部。

另一方面,如果堆栈也是一个数组,那么可能没有什么比单线程上的一些 memcpy 模拟更快了。

于 2013-01-09T07:46:04.940 回答