【发布时间】:2011-04-05 04:29:54
【问题描述】:
C++0x draft 有一个栅栏的概念,这似乎与 CPU/芯片级别的栅栏概念非常不同,或者说一下 linux 内核人员对 fences 的期望。问题是草案是否真的暗示了一个极其受限的模型,或者措辞很差,实际上暗示了真正的围栏。
例如,在 29.8 Fences 下,它声明如下:
释放栅栏 A 与 如果存在 atomic 则获取栅栏 B 操作 X 和 Y,都在 一些原子对象 M,使得 A 是 在 X 之前排序,X 修改了 M,Y 是 在 B 之前排序,Y 读取 X写入的值或写入的值 通过假设中的任何副作用 如果发布序列 X 是一个释放操作。
它使用这些术语atomic operations 和atomic object。草案中定义了这样的原子操作和方法,但是否仅指这些? 发布围栏听起来像商店围栏。不保证在栅栏之前写入所有数据的存储栅栏几乎是无用的。加载(获取)栅栏和完整栅栏类似。
那么,C++0x 中的栅栏/栅栏是不是适当的栅栏和措辞非常糟糕,或者它们是否像描述的那样受到严格限制/无用?
就 C++ 而言,假设我有这个现有代码(假设栅栏现在可以作为高级构造使用——而不是说在 GCC 中使用 __sync_synchronize):
Thread A:
b = 9;
store_fence();
a = 5;
Thread B:
if( a == 5 )
{
load_fence();
c = b;
}
假设 a,b,c 的大小可以在平台上进行原子复制。以上意味着c 将永远被分配9。请注意,我们并不关心线程 B 何时看到 a==5,只是在它看到时它也会看到 b==9。
C++0x中保证相同关系的代码是什么?
ANSWER:如果您阅读我选择的答案和所有 cmets,您将了解情况的要点。 C++0x 似乎迫使您使用带栅栏的原子,而普通的硬件栅栏没有这个要求。在许多情况下,只要sizeof(atomic<T>) == sizeof(T) 和atomic<T>.is_lock_free() == true,它仍然可以用来替换并发算法。
不幸的是,is_lock_free 不是 constexpr。这将允许它在static_assert 中使用。让atomic<T> 退化为使用锁通常是个坏主意:与使用互斥锁设计的算法相比,使用互斥锁的原子算法将存在可怕的争用问题。
【问题讨论】:
-
贫化铀已被取代为炮弹的首选材料。 C++0x 草案的过时副本被证明更加密集。
-
虽然只有一个月左右。
-
汉斯可能知道一些我们不知道的事情? C++11 真正的提案有望在下周发布。
-
为什么 ff 连字实际上是这样呈现的?
-
在规范中提及“原子操作”,无论是标准还是其他,只能引用该文档中描述为“原子操作”的那些操作,而不是其他任何没有的操作碰巧被视为完成了一半。
标签: c++ multithreading c++11 memory-barriers memory-model