2012-03-04 140 views
10

我想使用std :: atomic库。C++,C++ 11,std ::原子成员函数

  1. 什么之间的差别专业非专业原子 成员函数?
  2. 下列功能之间有什么区别(如果有的话)?
  3. 运算符=存储值到原子对象(公共成员函数)V.S. 商店(C++ 11)原子替换为一个非原子参数的原子对象的值(公共成员函数)
  4. 算子T()负载从一个原子对象的值(公共成员函数)V.S. 加载(C++ 11)自动获取原子对象(公共成员函数)的值。
  5. 操作者+ = V.S. fetch_add
  6. operator- = v.s. fetch_sub
  7. 运营商& = v.s. fetch_and
  8. 运营商| = v.s. fetch_or
  9. operator^= v.s. fetch_xor
  10. 什么是一个变量声明为原子V.S.的缺点一个 非原子变量。例如, std::atomic<int> x v.s.有什么缺点? int x?换句话说,一个原子变量的开销是多少?
  11. 哪一个有更多的开销?一个原子变量v.s.一个正常的 变量受互斥锁保护?

下面是引用我quesitons。 http://en.cppreference.com/w/cpp/atomic/atomic

+0

我认为这将是值得你花时间研究一个特定的架构原子CPU指令和内存屏障,以更好地了解如何实现原子操作的内部。请参阅此处以获取x86上的起点:http://www.mohawksoft.org/?q=node/78,并查找英特尔手册作为参考:http://www.intel.com/content/www/us /en/processors/architectures-software-developer-manuals.html – 2012-11-05 11:44:15

回答

10

不是专家,但我会尝试:

  1. 的特化(对于内置类型,如int)包含额外的操作,例如fetch_add。非专用表单(用户定义的类型)将不包含这些。
  2. operator=返回它的参数,store没有。另外,非运算符允许您指定一个内存顺序。该标准说operator=是根据store定义的。
  3. 与上面相同,但它返回的load值。
  4. 同上
  5. 同上
  6. 同上
  7. 同上
  8. 同上
  9. 同上
  10. 他们做不同的事情。在您使用std::atomic_int的方式中使用int的行为是未定义的。
  11. 你可以假定开销int <= std::atomic <= int and std::mutex其中<=意味着“更少的开销”。所以它可能比锁定互斥锁更好(特别是对于内置类型),但比int更糟糕。
+0

谢谢你的回复,你能解释一下什么是memory_order?我在这里找到了参考和几个例子,http://en.cppreference.com/w/cpp/atomic/memory_order。但是不太明白。 谢谢。 – 2607 2012-03-04 08:57:17

+1

@ 2607“memory_order”很难解释和理解。首先,你必须知道的一点是你总是应该使用'seq_cst',这是默认的默认值。第二个近似,可以将每个'原子'访问看作由访问之前获取的互斥体所保护,并在之后发布。与任何关键部分一样,其他程序操作可以转移到关键部分,但不能脱离。 “获取”语义允许其他操作向下移动但不起来; “释放”语义允许向上但不向下。第三个近似值,我不知道。 – Quuxplusone 2012-10-19 18:47:01

+0

std :: atomic被设计成在情况许可的情况下(例如,在x86上具有宽松内存顺序的情况下)与简单整数相比是无开销的。在这种情况下的另一个重要信息是std :: atomic可以在本机不支持这些操作的平台上以互锁方式实现算术运算。因此,一般来说,如果有足够的争论,这篇文章中的第二个不平等运营商可能(或不可能)转向。 – Dude 2012-10-20 13:35:54

0

我不是这个东西的专家,但如果我在你的参考正确理解非专业操作原子地做一两件事,加载,存储,更换等

的专业功能做两事物是原子性的,也就是说他们修改并返回一个原子对象,使得这两个操作在任何其他线程可能混淆它们之前发生。

9

什么专业和非专业的原子成员函数之间的区别?

如可以在这些类的在标准的synposis可以看出(§29.5),有三种不同的组成员函数:

  • 最通用的一个只提供存储,负载,交流和比较交换操作;
  • 除了通用类型之外,整数类型的专门化还提供原子算术和位运算;
  • 除了通用指针之外,指针专用还提供指针算术运算。

以下函数之间有什么区别(如果有的话)?

operator=将值存储到原子对象(公共成员函数)v.s.中。 store(C++ 11)原子替换为一个非原子参数的原子对象的值(公共成员函数)

(...)

主要的功能不同的是,非运算符版本(第29.6.5节,第9-17段和更多)具有用于指定所需内存排序(第29.3/1)的额外参数。运营商版本使用顺序一致性内存排序:

void A::store(C desired, memory_order order = memory_order_seq_cst) volatile noexcept; 
void A::store(C desired, memory_order order = memory_order_seq_cst) noexcept; 

要求:顺序参数不应memory_order_consumememory_order_acquire,也不memory_order_acq_rel

影响:原子上用对象或由此指向的值替换所需的值。根据order的值 ,内存受到影响。

C A::operator=(C desired) volatile noexcept; 
C A::operator=(C desired) noexcept; 

效果:store(desired)

返回:desired

非操作形式是有利的,因为顺序一致性并不总是必需的,并且它可能比更昂贵的其他记忆顺序。通过仔细分析,您可以找出正确操作所需的最低限度保证,并选择限制性较低的内存排序之一,为优化程序提供更多回旋余地。

将变量声明为原子v.s.的缺点是什么?一个非原子变量。例如,std::atomic<int> x v.s.有什么缺点? int x?换句话说,一个原子变量的开销是多少?

当常规变量足以限制可能的优化次数时使用原子变量,因为原子变量强加了不可分割性和(可能)内存排序的附加约束。

使用时需要一个原子变量可以引入数据争经常可变的,这使得未定义的行为(§1.10/ 21):

一个程序的执行包含数据争如果它在不同的线程中包含两个冲突的动作,其中至少有一个不是原子的,并且两个线程都不会发生在另一个线程之前。任何这样的数据竞争都会导致未定义的行为。

原子变量的开销是实现质量的问题。理想情况下,当您需要原子操作时,原子变量的开销为零。当你不需要原子操作时,它可能会有的开销是无关紧要的:你只需要使用一个常规变量。

哪一个有更多的开销?一个原子变量v.s.一个由互斥锁保护的正常变量?

没有理由为一个原子变量具有比互斥保护正常的变量更多的开销:最坏的情况下,原子变量实现就这样。但是有可能原子变量是无锁的,这会涉及更少的开销。该属性可以在标准§29.6.5/ 7所描述的功能来确定:

bool atomic_is_lock_free(const volatile A *object) noexcept; 
bool atomic_is_lock_free(const A *object) noexcept; 
bool A::is_lock_free() const volatile noexcept; 
bool A::is_lock_free() const noexcept; 

返回:真如果对象的操作是无锁的,否则为false。