让我们说一个FIFO(一个线程安全的)有一些项目被添加到它(我们不关心如何)
|__| |
| | |
|__| |
| | |
|__| V
| d|
|__|
| c|
|__|
| b|
|__|
| a|
现在假设应该将项目(逐个)插入另一个并发集合中。
数据插入率动态。
我想以最快的方式做到这一点。 (将所有元素从Fifo
转移到collection
)。
但是我发生了冲突:
我可以使用一个线程从Fifo
中提取项目并将其插入collection
。但后来我不会使用核心/其他可以帮助我的线程。
我可以使用多个消费者线程从Fifo
获取项目,但随后可能是Fifo
上的内部锁定(读取时),以及{{1}上的内部锁定(写作时)最终会降低性能。
我的意思是,如果我拥有庞大的消费者线程,将会有一个巨大的内部锁定与fifo /集合,加上许多上下文切换
如何以正确的方式解决这类问题?什么是指南?
答案 0 :(得分:1)
争用同一个并发集合的多个线程将始终是一个瓶颈情况。您拥有的线程越多,问题通常越严重,但降级速度取决于锁定机制。我希望.NET 4.0中的新并发集合是无锁的,或者至少使用非阻塞锁,因此它们在某种程度上应该是对争用友好的。
由于这个问题似乎是开放式的,我建议您只是尝试不同数量的线程,并在fifo争用和您想要实现的吞吐量之间找到平衡。
答案 1 :(得分:0)
如果您在集合之间进行最少的处理,请仅使用一个线程。如果您有多个目标集合,则可能需要使用多个线程。或者,如果两端的数据结构都是具有高级锁定的复杂结构,它实际上支持多线程插入,而不仅仅是锁定内容。
答案 2 :(得分:0)
我会考虑使用任务并行库(TPL)。
你可以保留一个队列,当它有项目时,让并行框架为你完成所有繁重的工作。无需使用所有毛茸茸的代码管理线程来处理自己的线程池。
必须承认我自己还没有这样做,但是如果我在你的情况下我会刷新我的TPL技能并开始考虑任务而不是线程x。
答案 3 :(得分:0)
如果我们可以访问两个集合的内部,可以通过几个非交互线程来完成。例如,如果该堆栈是已知大小的链接列表,则两个线程可以从两端处理它直到它们相遇,并且它们可以构建新的链接列表,其中一个将元素附加到尾部而另一个附加到头部。
另一方面,如果堆栈也是一个数组,那么在单个线程上可能没有什么比memcpy的模拟更快。