首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11原子类和操作--我说得对吗

C++11原子类和操作--我说得对吗
EN

Stack Overflow用户
提问于 2014-02-28 08:52:46
回答 1查看 368关注 0票数 5

以下假设是正确的吗?

  • 我不需要使用自己的同步对象显式地同步访问来自任何平台上不同线程的std::atomic<T>对象
  • std::atomic<T>操作可以是无锁的,也可以是非无锁的,取决于平台。
  • std::atomic_boolstd::atomic<bool> (以及其他类似的类型)实际上是相同的
  • std::atomic_flag是唯一按标准保证平台无关的无锁操作的类。

另外,在哪里可以找到关于std::memory_order的有用信息,以及如何正确地使用它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-28 16:56:20

让我们一个接一个地检查一下。

  • 我不需要使用自己的同步对象显式地同步访问来自任何平台上不同线程的std::atomic<T>对象

是的,atomic对象在其所有访问器方法上都是完全同步的。

在访问原子类型时,唯一可能发生的数据争用发生在构造过程中,但它涉及构造原子对象A,通过使用memory_order_relaxed的原子指针将其地址传递给另一个线程,从而有意地绕过std::atomic的顺序一致性,然后从第二个线程访问A。所以,不要那么做?:)

说到构造,有三种方法可以初始化原子类型:

代码语言:javascript
复制
// Method 1: constructor
std::atomic<int> my_int(5);

// Method 2: atomic_init
std::atomic<int> my_int; // must be default constructed
std::atomic_init(&my_int, 5); // only allowed once

// Method 3: ATOMIC_VAR_INIT
// may be implemented using locks even if std::atomic<int> is lock-free
std::atomic<int> my_int = ATOMIC_VAR_INIT(5);

使用后两种方法中的任何一种,同样的数据竞争可能性也适用。

  • std::atomic<T>操作可以是无锁的,也可以是非无锁的,取决于平台。

对,是这样。对于所有的整体类型,您可以检查一些宏,这些宏可以告诉您给定的atomic专门化是否有时是无锁的,还是始终是无锁的。对于这三种情况,宏的值分别为0、1或2。宏的完整列表摘自标准的第29.4节,其中unspecified是"0、1或2“的替补:

代码语言:javascript
复制
#define ATOMIC_BOOL_LOCK_FREE unspecified 
#define ATOMIC_CHAR_LOCK_FREE unspecified 
#define ATOMIC_CHAR16_T_LOCK_FREE unspecified 
#define ATOMIC_CHAR32_T_LOCK_FREE unspecified 
#define ATOMIC_WCHAR_T_LOCK_FREE unspecified 
#define ATOMIC_SHORT_LOCK_FREE unspecified 
#define ATOMIC_INT_LOCK_FREE unspecified 
#define ATOMIC_LONG_LOCK_FREE unspecified 
#define ATOMIC_LLONG_LOCK_FREE unspecified 
#define ATOMIC_POINTER_LOCK_FREE unspecified

请注意,这些定义同时适用于相应类型的无符号变体和符号变体。

如果#define为1,则必须在运行时进行检查。实现这一目标的步骤如下:

代码语言:javascript
复制
std::atomic<int> my_int;

if (my_int.is_lock_free()) {
    // do lock-free stuff
}

if (std::atomic_is_lock_free(&my_int)) {
    // also do lock-free stuff
}
  • std::atomic_boolstd::atomic<bool> (以及其他类似的类型)实际上是相同的

是的,为了您的方便,这些都是typedef。完整的清单载于标准表194:

代码语言:javascript
复制
Named type      | Integral argument type
----------------+-----------------------
atomic_char     | char
atomic_schar    | signed char
atomic_uchar    | unsigned char
atomic_short    | short
atomic_ushort   | unsigned short
atomic_int      | int
atomic_uint     | unsigned int
atomic_long     | long
atomic_ulong    | unsigned long
atomic_llong    | long long
atomic_ullong   | unsigned long long
atomic_char16_t | char16_t
atomic_char32_t | char32_t
atomic_wchar_t  | wchar_t
  • std::atomic_flag是唯一按标准保证平台无关的无锁操作的类。

正确,如标准第29.7/2节所保证。

请注意,除非您使用宏初始化atomic_flag,否则无法保证它的初始化状态如下:

代码语言:javascript
复制
std::atomic_flag guard = ATOMIC_FLAG_INIT; // guaranteed to be initialized cleared

其他原子类型也有类似的宏,

该标准没有指定atomic_flag是否可以在构造过程中经历其他原子类型可能具有的相同的数据竞争。

  • 另外,在哪里可以找到关于std::memory_order的有用信息,以及如何正确地使用它?

正如@WhozCraig所建议的,cppreference.com有最好的参考资料。

正如@erenon所暗示的,Boost.Atomic有一篇关于如何使用内存栅栏进行无锁编程的优秀文章。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22090348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档