C++编译器如何支持C++11原子,但不支持C++11内存模型
How can C++ compilers support C++11 atomic, but not support C++11 memory model
在查看Clang和g ++ C++11实现状态时,我注意到了一些奇怪的事情:
它们支持 C++11 原子组学,但不支持 C++11 内存模型。
我的印象是,你必须有C++11记忆模型才能使用原子学。那么,对原子的支持和内存模型之间究竟有什么区别呢?
缺少内存模型支持是否意味着使用std::atomic<T>
的合法 C++11 程序不一致?
引用:
http://clang.llvm.org/cxx_status.htmlhttp://gcc.gnu.org/gcc-4.7/cxx0x_status.html
问题是"内存位置"的定义,它允许(并强制编译器支持)通过不同的锁锁定不同的结构成员。有一个关于由此引起的 RL 问题的讨论。
基本上问题是struct
struct x {
long a;
unsigned int b1;
unsigned int b2:1;
};
编译器也可以通过覆盖b1
来自由地实现对b2
的写入(显然,从报告来看,它确实如此)。因此,这两个字段必须锁定为一个字段。但是,由于 C++11 内存模型,这是被禁止的(好吧,并不是真正禁止的,但编译器必须确保同时更新b1
并且b2
不会干扰;它可以通过锁定或 CAS 来做到这一点,嗯,在某些架构上生活很困难)。引用报告:
我已经向我们的海湾合作委员会的人提出了这个问题,他们对我说:"C确实 不提供此类保证,也无法可靠地锁定不同的 具有不同锁的结构字段(如果它们共享自然对齐) 字大小的内存区域。 C++11 内存模型将保证这一点, 但这没有实现,也没有使用 C++11 构建内核 编译器。
不错的信息也可以在维基中找到。
我想在这些情况下的"缺少内存模型"只是意味着优化器是在 C++11 内存模型发布之前编写的,并且现在可能会执行无效的优化。针对内存模型验证优化非常困难且耗时,因此 clang/gcc 团队尚未完成此操作也就不足为奇了。
缺少内存模型支持是否意味着使用 std::atomic 的合法 C++11 程序不一致?
是的,这是一种可能性。更糟糕的是:编译器可能会将数据竞赛引入(根据C++11标准)无竞赛程序,例如通过引入推测写入。
例如,用于执行此优化的几个C++编译器:
for (p = q; p = p -> next; ++p) {
if (p -> data > 0) ++count;
}
可以优化为:
register int r1 = count;
for (p = q; p = p -> next; ++p) {
if (p -> data > 0) ++r1;
}
count = r1;
如果所有p->data
都是非负数,则原始源代码不会写入count
,但优化的代码会写入。这可能会在无竞争程序中引入数据竞争,因此 C++11 规范不允许此类优化。现有编译器现在必须验证(并在必要时调整)所有优化。
有关详细信息,请参阅并发内存模型编译器结果。
并不是说它们不支持内存模型,而是它们(尚)不支持标准中用于与内存模型交互的 API。 该 API 包含许多互斥锁。
然而,Clang和GCC都有一段时间没有正式标准的情况下尽可能了解线程。 您不必担心优化会将内容移动到原子操作的错误一侧。
- C++11:具有互斥锁的线程看到原子变量的值发生变化,尽管这是唯一可以改变它的代码
- C++11:16 字节原子<>变量是否在 16 字节边界上自动对齐,从而允许CMPXCHG16B指令?
- C++11 原子<>:只能使用提供的方法读取/写入?
- 对 c++ 11 原子变量的操作实际上是原子的
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- 如何使用原子操作fetch_or或test_and_set在指针中设置一点,而在C 11中不使用Amberare_
- 如何使用 C++11 实现指向整数的指针的原子增量<atomic>?
- C 11解释原子和静音
- 什么是C 11原子类
- 如何使用c++11原子库实现seqlock锁
- C++编译器如何支持C++11原子,但不支持C++11内存模型
- 执行 c++ 11 原子对象也是原子的吗?
- C++11 原子排序:锁的扩展总顺序memory_order_seq_cst
- C++11 原子<T>可用于 mmap 吗?
- 使用c++11原子编写(旋转)线程屏障
- c++ 11原子库std::compare_and_exchange语义
- 如何使用c++ 11原子控制线程生存期
- c++ 11原子.为什么这个编译,而不是链接
- C++11 原子内存排序 - 这是宽松(释放-消耗)排序的正确用法吗?
- 什么是 C++11 原子 API 等同于"__asm__易失性( " " ::: "memory" )"''