我在以下假设中是对的:
std::atomic<T>
对象的访问权std::atomic<T>
操作可以是无锁的,也可以是非锁定的,具体取决于平台std::atomic_bool
和std::atomic<bool>
(以及其他类似的)实际上是相同的事情std::atomic_flag
是唯一一个通过标准另外,我在哪里可以找到有关std::memory_order
的有用信息以及如何正确使用它?
答案 0 :(得分:6)
让我们逐一介绍。
std::atomic<T>
对象的访问权是的,atomic
个对象在其所有访问器方法上完全同步。
在构造期间,只有在访问原子类型时才能发生数据争用,但它涉及构建原子对象A
,使用memory_order_relaxed
通过原子指针将其地址传递给另一个线程故意解决std::atomic
的顺序一致性,然后从第二个线程访问A
。那么,不要那样做? :)
说到构造,有三种方法可以初始化原子类型:
// 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”的替代值:
#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,则必须在运行时进行检查。这完成如下:
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_bool
和std::atomic<bool>
(以及其他类似的)实际上是相同的事情是的,为方便起见,这些只是typedef
。完整列表见标准表194:
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
的初始化状态无法保证,除非您使用宏对其进行初始化,如下所示:
std::atomic_flag guard = ATOMIC_FLAG_INIT; // guaranteed to be initialized cleared
其他原子类型有一个类似的宏,
该标准未指定atomic_flag
是否可能在构建期间遇到其他原子类型可能存在的相同数据竞争。
std::memory_order
的有用信息以及如何正确使用它?根据@WhozCraig的建议,cppreference.com有最好的参考。
正如@erenon所暗示的那样,Boost.Atomic有一篇关于如何使用内存栅栏进行无锁编程的精彩文章。