要MultiThread还是不MultiThread?

时间:2013-01-09 07:20:04

标签: c# multithreading .net-4.0

让我们说一个FIFO(一个线程安全的)有一些项目被添加到它(我们不关心如何

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

现在假设应该将项目(逐个)插入另一个并发集合中。

数据插入率动态

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

但是我发生了冲突:

  • 我可以使用一个线程从Fifo中提取项目并将其插入collection。但后来我不会使用核心/其他可以帮助我的线程。

  • 我可以使用多个消费者线程从Fifo获取项目,但随后可能是Fifo上的内部锁定(读取时),以及{{1}上的内部锁定(写作时)最终会降低性能。

我的意思是,如果我拥有庞大的消费者线程,将会有一个巨大的内部锁定与fifo /集合,加上许多上下文切换

如何以正确的方式解决这类问题?什么是指南?

4 个答案:

答案 0 :(得分:1)

争用同一个并发集合的多个线程将始终是一个瓶颈情况。您拥有的线程越多,问题通常越严重,但降级速度取决于锁定机制。我希望.NET 4.0中的新并发集合是无锁的,或者至少使用非阻塞锁,因此它们在某种程度上应该是对争用友好的。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

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