问题
摘要:并行地将函数F应用于数组的每个元素,其中F不是线程安全的
我有一组元素E要处理,比如说它们的队列。我想使用相同的函数f(E(并行处理所有这些元素。
现在,理想情况下,我可以调用基于映射的并行模式,但问题有以下限制。
- 每个元素包含一对2个对象。(E=(A,B((
- 两个元素可以共享一个对象。(E1=(A1,B1(;E2=(A1,B2(
- 函数f不能处理共享一个对象的两个元素。因此E1和E2不能并行处理
做这件事的正确方法是什么?
我的想法是这样的,
- 琐碎的想法:保持一组活动的a和B,只有当没有其他线程已经在使用a或B时才开始处理元素。
- 因此,当您将元素赋予线程时,您会将As和Bs添加到活动集
- 拾取第一个元素,如果它的元素不在活动集中,则生成一个新线程,否则将其推到元素队列的后面
- 这样做直到队列为空
- 这会造成僵局吗?理想情况下,当处理结束时,一些元素将变得可用,对吗
2.-另一个想法是把这些相连的物体做成一张图。每个节点表示一个对象(A/B(。每个元素都是连接A&B、 然后以某种方式处理数据,这样我们就知道元素永远不会重叠。
问题
- 我们如何才能做到最好
- 有标准的模式吗
- 这些方法有问题吗
- 没有必要,但如果你能告诉TBB方法使用,那就太好了
"最佳"方法取决于许多因素:
- 你有多少元素"E",f(E(需要做多少功。-->检查并行处理元素是否真的值得(如果你需要大量的锁定,并且没有太多的工作要做,你可能会通过并行处理来减缓这个过程(
- 有没有可能改变可以使f(E(多线程安全的设计
- 有多少个元素"A"one_answers"B"?元素"E"共享A和B的特定版本有什么逻辑吗?-->如果您可以将元素E排序为单独的列表,其中每个A和B只出现在一个列表中,那么您可以并行处理这些列表,而无需任何进一步的锁定
- 如果有很多不同的A和B,而你没有分享太多,你可能想做一个琐碎的方法,在输入时只锁定每个"A"one_answers"B",然后等待锁定
无论何时使用多个锁进行"锁定并等待",都必须始终以相同的顺序获取锁(例如总是A第一个和B第二个(,否则可能会遇到死锁。这种锁定顺序需要在任何地方都遵守(整个应用程序中使用不同顺序的单个位置都可能导致死锁(
编辑:此外,如果您执行"try-lock",则需要确保订单始终相同。否则,你可能会造成救生锁:
- 螺纹1锁定A
- 螺纹2锁B
- 线程1试图锁定B,但失败
- 线程2试图锁定A,但失败
- 线程1释放锁A
- 线程2释放锁B
- 转到1并重复
这种情况"无休止"发生的可能性相对较小,但无论如何都应该避免
编辑2:主要是我想我会根据Ax将E(Ax,Bx(划分为不同的列表(例如,共享相同A的所有E的一个列表(。然后在锁定"B"的同时处理这些列表(在那里,如果已经使用了所需的B,您仍然可以"TryLock"并继续。