一般地,对于int num,num++(或++num),作为读-修改-写操作中,是不是原子.但我经常看到编译器,例如GCC,为它生成以下代码(在这里尝试):
由于第5行对应于num++一条指令,我们可以得出结论,在这种情况下num++ 是原子的吗?
如果是这样,是否意味着如此生成num++可以在并发(多线程)场景中使用而没有任何数据争用的危险(例如,我们不需要制作它,std::atomic<int>并强加相关成本,因为它是无论如何原子)?
UPDATE
请注意,这个问题不是增量是否是原子的(它不是,而且是问题的开头行).它是否可以在特定场景中,即在某些情况下是否可以利用单指令性质来避免lock前缀的开销.而且,作为公认的答案约单处理器的机器,还有部分提到这个答案,在其评论和其他人谈话解释,它可以(尽管不是C或C++).
单个进程中的两个不同线程可以通过读取和/或写入来共享公共存储器位置.
通常,这种(有意)共享是使用lockx86上的前缀使用原子操作实现的,该前缀对于lock前缀本身(即,无竞争成本)具有相当广为人知的成本,并且当实际共享高速缓存行时还具有额外的一致性成本(真或假共享).
在这里,我对生产 - 消费者成本感兴趣,其中单个线程P写入内存位置,另一个线程`C从内存位置读取,都使用普通读取和写入.
在同一个套接字上的不同内核上执行此类操作的延迟和吞吐量是多少,并且在最近的x86内核上在同一物理内核上执行兄弟超线程时进行比较.
在标题中,我使用术语"超级兄弟"来指代在同一核心的两个逻辑线程上运行的两个线程,以及核心间兄弟,以指代在不同物理核心上运行的两个线程的更常见情况.
8.2.3.4负载可以通过早期存储
重新排序到不同位置 Intel-64内存排序模型允许将负载与早期存储重新排序到不同位置.但是,加载不会与商店重新排序到同一位置.
那些与之前的商店部分或完全重叠但是没有相同起始地址的负载呢?(有关具体案例,请参阅本文末尾)
假设以下类似C的代码:
// lock - pointer to an aligned int64 variable
// threadNum - integer in the range 0..7
// volatiles here just to show direct r/w of the memory as it was suggested in the comments
int TryLock(volatile INT64* lock, INT64 threadNum)
{
if (0 != *lock)
return 0; // another thread already had the lock
((volatile INT8*)lock)[threadNum] = 1; // take the lock by setting our byte
if (1LL << 8*threadNum != …Run Code Online (Sandbox Code Playgroud)