如何在不使用C+;中的锁的情况下防止竞争条件+;? 我如何防止没有锁或使用C++中的互斥/信号量的竞争条件?我正在处理嵌套for循环,在该循环中,我将在数组中设置一个值: for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) for (int k = 0; k < o; ++k) array[k] += foo(...); for(int i=0;i

如何在不使用C+;中的锁的情况下防止竞争条件+;? 我如何防止没有锁或使用C++中的互斥/信号量的竞争条件?我正在处理嵌套for循环,在该循环中,我将在数组中设置一个值: for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) for (int k = 0; k < o; ++k) array[k] += foo(...); for(int i=0;i,c++,race-condition,icc,C++,Race Condition,Icc,或多或少,我想处理这个问题,这样我就可以确保同时运行的不同线程不会同时写入数组[k]。关于如何处理这个问题有什么建议吗 编辑:我在Linux机器上运行,还必须使用英特尔编译器。我将使用“icc”而不是“gcc”来编译代码。假设数组包含整数,请使用gcc的\uuuuu同步\uu获取\u和\uu添加应该可以做到这一点。对于这个特定的循环,请将其翻过来。将k放在外部,然后您可以将k=0转移到与k=1不同的线程,依此类推 只要foo()不依赖于数组[k],其中k!=它是当前的k,那么您是金色的。假设wi

或多或少,我想处理这个问题,这样我就可以确保同时运行的不同线程不会同时写入数组[k]。关于如何处理这个问题有什么建议吗


编辑:我在Linux机器上运行,还必须使用英特尔编译器。我将使用“icc”而不是“gcc”来编译代码。

假设数组包含整数,请使用gcc的<代码>\uuuuu同步\uu获取\u和\uu添加应该可以做到这一点。

对于这个特定的循环,请将其翻过来。将
k
放在外部,然后您可以将
k=0
转移到与
k=1
不同的线程,依此类推


只要
foo()
不依赖于数组[k],其中k!=它是当前的k,那么您是金色的。

假设windows和
数组
包含
LONG
类型的元素,您可以执行以下操作:

for (int i = 0; i < m; ++i) 
   for (int j = 0; j < n; ++j) 
      for (int k = 0; k < o; ++k)  {
          LONG val = foo(...);
          InterlockedAdd( &array[k], val);
      }
据我所知,Boost对原子/联锁操作的支持有限,显然只足以支持引用计数的原子操作。我不认为Boost中对互锁操作的支持超过了实现细节(我目前正在处理一个稍旧的Boost版本,因此可能不再如此)

有些可移植库支持原子比较和交换以及其他原子操作,作为接口的文档部分:

  • 阿帕奇APR:
  • 油嘴滑舌的:
  • 英特尔线程构建块:

还注意到C++ +0x将支持对原子操作(如比较/交换)的支持,我不确定当前C++编译器中支持的级别(它似乎不是VS 2010)。

< P>在线程之间划分最内层循环。线程T1处理范围[0,L]中的索引,线程T2处理范围[L,2L]中的索引,等等。L=o/n,其中n是线程数。这假设foo()调用不使用可能同时计算的其他位置

编辑:如其他人所建议的,使用互锁操作将给出正确的结果,但可能会严重降低性能。(如果内部循环很短,许多线程将争夺很少的内存位置,这将有效地序列化您的程序。)

最简单的方法(尽管不是最有效的!)是将循环包装为“关键的”节


请参见此处,这将在任何给定时间将循环代码限制为单个线程。

按照您希望的方式,它无法完成!(请参见sbi的注释)

您可以使用共享内存,但仍会有锁。
您也可以只使用一个线程来写入和读取数组。如果您认为为它设置正确的协议更容易,请继续

无论如何,已经有使用锁(直接或间接)的好解决方案了

使用联锁操作,如 其他人已经建议,将给予 结果正确,但可能会降级 性能差。(如果内部循环 如果是短线程,则将使用多个线程 争夺少量内存位置, 这将有效地序列化您的 程序)链接|标志

不是真的,我的朋友。 实际上,联锁操作优于所有类型的锁定。更准确地说:所有同步对象(关键部分、互斥体、事件等)都是按照联锁操作来实现的。 实际上,互锁操作是唯一可以保证同步一致性的处理器指令。如果不使用互锁操作,根本不可能实现同步对象

另一个问题是锁定的范围。您可能想说,内部循环中的同步范围(使用同步对象或直接使用联锁操作实现)可能会导致性能下降,因为它执行了多次


嗯,这是真的。但另一方面,你只在需要的时间内锁定你需要的东西。因此你可以防止潜在的同步冲突。

哪个操作系统?或者你使用boost库?我有点困惑。在标题中你要求一个没有锁的解决方案,在问题中你想要锁定吗?不!我不想要锁定。我道歉为了让它看起来像我想要锁。请告诉我我把你弄糊涂了,这样我就可以编辑它。在你的第一句话中:“我如何阻止在锁定或使用C++中的互斥/信号量的竞争条件?”.这三个都要求锁:)为什么不想使用锁?那么哪些同步方法是可以接受的?原子指令?更高级别的抽象,如STM?对于这个特定的程序,我将使用intel的编译器。我不确定这是否意味着我不能使用“gcc的原子内置”我喜欢你的想法。不过我不太明白。你说“只要foo()不依赖于数组[k]其中k!=它是当前的k”是什么意思?小心。缓存可能会对你不利。哦,我的意思是,如果
foo()
依赖于
array[0]
当它试图计算
array[1]
,那么您将需要解决比使用Marcelo的建议或类似建议更困难的同步问题。不…foo()不依赖于数组[index]那么从概念上讲,把它翻过来对我的情况有什么帮助呢?它所做的是,它给你不同的工作单元,每个工作单元彼此独立。你可以通过
i=0..m,j=0..n
将相同的循环分配给不同的线程,
k
每个不同的值一个。因为我试图提高执行
 int InterlockedAdd( int volatile* pDest, int operand)
 {
      int curval = *pDest;
      int oldval;

      do {
           oldval = curval;
           curval = InterlockedCompareExchange( pDest, oldval + operand, oldval);
      } while (curval != oldval);

      return oldval+operand;
 }