C++ 中的原子性:神话还是现实 [重复]

2024-01-13

我读过一篇关于无锁编程 http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx在 MSDN 中。它说 :

在所有现代处理器上,您可以 假设读取和写入自然对齐的本机类型是原子的。只要内存总线是 至少与类型一样宽 读或写,CPU读取和 将这些类型写入单个总线中 交易,使得无法进行 其他线程中查看它们 半完成状态。

它给出了一些例子:

// This write is not atomic because it is not natively aligned.
DWORD* pData = (DWORD*)(pChar + 1);
*pData = 0;

// This is not atomic because it is three separate operations.
++g_globalCounter;

// This write is atomic.
g_alignedGlobal = 0;

// This read is atomic.
DWORD local = g_alignedGlobal;

我读了很多答案和评论说,在 C++ 中没有什么可以保证是原子的,甚至在标准中也没有提到,在 SO 中,现在我有点困惑。我是否误解了这篇文章?或者文章作者是否谈论了非标准且特定于 MSVC++ 编译器的内容?

所以根据这篇文章,下面的赋值必须是原子的,对吗?

struct Data
{
    char ID;
    char pad1[3];
    short Number;
    char pad2[2];
    char Name[5];
    char pad3[3];
    int Number2;
    double Value;
} DataVal;

DataVal.ID = 0;
DataVal.Number = 1000;
DataVal.Number2 = 0xFFFFFF;
DataVal.Value = 1.2;

如果是真的,是否替换Name[5] and pad3[3] with std::string Name;内存对齐有什么不同吗?将作业分配给Number2 and Value变量仍然是原子的吗?

有人可以解释一下吗?


此建议是特定于体系结构的。对于 x86 和 x86_64 来说也是如此(在低级编程中)。您还应该检查编译器是否不会重新排序您的代码。您可以为此使用“编译器内存屏障”。

英特尔参考手册“英特尔® 64 和 IA-32 架构软件开发人员手册”第 3A 卷中描述了 x86 的低级原子读写(http://www.intel.com/Assets/PDF/manual/253668.pdf http://www.intel.com/Assets/PDF/manual/253668.pdf),第 8.1.1 节

8.1.1 有保证的原子操作

Intel486 处理器(以及此后更新的处理器)保证以下特性 基本的内存操作将始终以原子方式执行:

  • 读取或写入一个字节
  • 读取或写入在 16 位边界上对齐的字
  • 读取或写入在 32 位边界上对齐的双字

奔腾处理器(以及此后更新的处理器)保证以下特性 额外的内存操作将始终以原子方式执行:

  • 读取或写入在 64 位边界上对齐的四字
  • 对适合 32 位数据总线的未缓存内存位置进行 16 位访问

P6 系列处理器(以及此后更新的处理器)保证以下特性 额外的内存操作将始终以原子方式执行:

  • 对适合高速缓存的高速缓存内存进行未对齐的 16 位、32 位和 64 位访问 线

本文档还对 Core2 等较新处理器的原子性进行了更多描述。并非全部不对齐操作将是原子的。

其他intel手册推荐这个白皮书:

http://software.intel.com/en-us/articles/developing-multithreaded-applications-a-platform-concient-approach/ http://software.intel.com/en-us/articles/developing-multithreaded-applications-a-platform-consistent-approach/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中的原子性:神话还是现实 [重复] 的相关文章

随机推荐