一般地,对于int num,num++(或++num),作为读-修改-写操作中,是不是原子.但我经常看到编译器,例如GCC,为它生成以下代码(在这里尝试):
由于第5行对应于num++一条指令,我们可以得出结论,在这种情况下num++ 是原子的吗?
如果是这样,是否意味着如此生成num++可以在并发(多线程)场景中使用而没有任何数据争用的危险(例如,我们不需要制作它,std::atomic<int>并强加相关成本,因为它是无论如何原子)?
UPDATE
请注意,这个问题不是增量是否是原子的(它不是,而且是问题的开头行).它是否可以在特定场景中,即在某些情况下是否可以利用单指令性质来避免lock前缀的开销.而且,作为公认的答案约单处理器的机器,还有部分提到这个答案,在其评论和其他人谈话解释,它可以(尽管不是C或C++).
我正在尝试使用OpenMP以并行方式在双精度数组中编写(更新).我们的想法是,需要更新的元素可以多次更新,并且元素本身可以即时计算.这使得它非常容易出现竞争条件,除非我"锁定"与使用原子操作更新的元素相对应的内存区域.如下例所示:
#include<omp.h>
#include<stdlib.h>
int main()
{
double *x=NULL, contribution = 1234.5;
size_t xlen=1000, i, n;
if ( (x = (double *) calloc(xlen,sizeof(double)) ) == NULL) exit(-1)
#pragma omp parallel for shared(x) private(n,contribution)
for (i=0; i<xlen; i++) {
n = find_n_on_the_fly(i);
#pragma omp atomic update
x[n]+=contribution; // in the more complicated case contributions are different
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我仍然在用这种方法遇到竞争条件.我尝试使用关键部分,但它完全杀了我,因为数组很大,更新的数量也很大.
问题:这种方法有什么问题?有没有更好的方法来处理这个?
注意:为了解决这个问题,我通过为每个线程创建数组的副本并在以后减少它们来做一些愚蠢的事情.但内存限制不允许我走得更远.