C++0x 草案有一个栅栏的概念,这似乎与 CPU/芯片级别的栅栏概念非常不同,或者说 linux 内核人员对栅栏的期望。问题是草案是否真的暗示了一个极其受限的模式,或者措辞很差,实际上暗示了真正的围栏。
例如,在29.8 Fences下,它声明如下:
如果存在原子操作 X 和 Y,则释放栅栏 A 与获取栅栏 B 同步,两者都对某个原子对象 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 中保证相同关系的代码是什么?
答案:如果您阅读我选择的答案和所有评论,您将了解情况的要点。C++0x 似乎迫使您使用带栅栏的原子,而普通的硬件栅栏没有这个要求。在许多情况下,只要sizeof(atomic<T>) == sizeof(T)
和 ,这仍然可以用来替换并发算法atomic<T>.is_lock_free() == true
。
不幸的是,这is_lock_free
不是 constexpr。这将允许它在static_assert
. 退化atomic<T>
为使用锁通常是一个坏主意:与使用互斥锁设计的算法相比,使用互斥锁的原子算法将存在可怕的争用问题。