)
C11 并发指南六(atomic 类型详解四 C 风格原子操作介绍)前面三篇文章《C11 并发指南六(atomic 类型详解一 atomic_flag 介绍)》、《C11 并发指南六( 类型详解二 std::atomic )》、《C11 并发指南六(atomic 类型详解三 std::atomic (续))》都是采用 C 的方式介绍原子对象本节我会给大家介绍 C11 原子操作中 C 风格的 API。总地来说C11 标准中规定了两大类原子对象std::atomic_flag 和 std::atomic前者 std::atomic_flag 一种最简单的原子布尔类型只支持两种操作test-and-set 和 clear。而 std::atomic 是模板类一个模板类型为 T 的原子对象中封装了一个类型为 T 的值并且C11 标准中除了定义基本 std::atomic 模板类型外还提供了针对整形(integral)和指针类型的特化实现提供了大量的 API极大地方便了开发者使用。下面我分别介绍基于 std::atomic_flag 和 std::atomic 的 C 风格 API。文章目录C11 并发指南六(atomic 类型详解四 C 风格原子操作介绍)基于 std::atomic_flag 类型的 C 风格 API基于 std::atomic 模板类型的 C 风格 API与原子对象初始化相关的宏基于 std::atomic_flag 类型的 C 风格 APIatomic_flag_test_and_setbool atomic_flag_test_and_set (volatile atomic_flag* obj) noexcept; bool atomic_flag_test_and_set (atomic_flag* obj) noexcept;检测并设置 std::atomic_flag 的值并返回 std::atomic_flag 的旧值和 std::atomic::test_and_set() 成员函数的功能相同整个过程也是原子的默认的内存序为memory_order_seq_cst。atomic_flag_test_and_set_explicitbool atomic_flag_test_and_set (volatile atomic_flag* obj, memory_order sync) noexcept; bool atomic_flag_test_and_set (atomic_flag* obj, memory_order sync) noexcept;检测并设置 std::atomic_flag 的值并返回 std::atomic_flag 的旧值和 std::atomic::test_and_set() 成员函数的功能相同整个过程也是原子的。sync 参数指定了内存序Memory Order可能的取值如下Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_flag_clearvoid atomic_flag_clear (volatile atomic_flag* obj) noexcept; void atomic_flag_clear (atomic_flag* obj) noexcept;清除 std::atomic_flag 对象并设置它的值为 false和 std::atomic::clear() 成员函数的功能相同整个过程也是原子的默认的内存序为memory_order_seq_cst。atomic_flag_clear_explicitvoid atomic_flag_clear (volatile atomic_flag* obj, memory_order sync) noexcept; void atomic_flag_clear (atomic_flag* obj, memory_order sync) noexcept;清除 std::atomic_flag 对象并设置它的值为 false和 std::atomic::clear() 成员函数的功能相同整个过程也是原子的sync 参数指定了内存序Memory Order可能的取值如下Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistent基于 std::atomic 模板类型的 C 风格 APIatomic_is_lock_freetemplate (1)template bool atomic_is_lock_free (const volatile atomic* obj) noexcept; template bool atomic_is_lock_free (const atomic* obj) noexcept;overloads (2)bool atomic_is_lock_free (const volatile A* obj) noexcept; bool atomic_is_lock_free (const A* obj) noexcept;判断该 std::atomic 对象是否具备 lock-free 的特性。如果某个对象满足lock-free特性在多个线程访问该对象时不会导致线程阻塞。(可能使用某种事务内存transactional memory方法实现 lock-free 的特性)。atomic_inittemplate (1)template class T void atomic_init (volatile atomicT* obj, T val) noexcept; template class T void atomic_init (atomicT* obj, T val) noexcept;overloads (2)void atomic_init (volatile A* obj, T val) noexcept; void atomic_init (A* obj, T val) noexcept;初始化原子对象。val 指定原子对象的初始值。如果对一个已初始化的原子对象再次调用 atomic_init()则会导致未定义行为(undefined behavior)如果你想修改原子对象的值应该使用 std::atomic_store();atomic_storetemplate (1)template class T void atomic_store (volatile atomicT* obj, T val) noexcept; template class T void atomic_store (atomicT* obj, T val) noexcept;overloads (2)void atomic_store (volatile A* obj, T val) noexcept; void atomic_store (A* obj, T val) noexcept;修改原子对象的值默认的内存序为memory_order_seq_cst。该函数相当于 std::atomic 对象的 store 或者operator() 成员函数如果你需要显式指定内存序应该使用atomic_store_explicit。atomic_store_explicit修改原子对象的值。该函数相当于 std::atomic 对象的 store 或者operator() 成员函数sync 指定了内存序可取的参数为Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_releaseReleasememory_order_seq_cstSequentially consistentatomic_loadtemplate (1)template class T T atomic_load (const volatile atomicT* obj) noexcept; template class T T atomic_load (const atomicT* obj) noexcept;overloads (2)T atomic_load (const volatile A* obj) noexcept; T atomic_load (const A* obj) noexcept;读取被封装的值默认的内存序为memory_order_seq_cst。该函数与 std::atomic 对象的atomic::load()和atomic::operator T() 成员函数等价。atomic_load_explicittemplate (1)template class T T atomic_load_explicit (const volatile atomicT* obj, memory_order sync) noexcept; template class T T atomic_load_explicit (const atomicT* obj, memory_order sync) noexcept;overloads (2)T atomic_load_explicit (const volatile A* obj, memory_order sync) noexcept; T atomic_load_explicit (const A* obj, memory_order sync) noexcept;读取被封装的值参数 sync 设置内存序(Memory Order)可能的取值如下Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_seq_cstSequentially consistent该函数与 std::atomic 对象的atomic::load() 成员函数等价。atomic_exchangetemplate (1)template class T T atomic_exchange (volatile atomicT* obj, T val) noexcept; template class T T atomic_exchange (atomicT* obj, T val) noexcept;overloads (2)T atomic_exchange (volatile A* obj, T val) noexcept; T atomic_exchange (A* obj, T val) noexcept;读取并修改被封装的值exchange 会将 val 指定的值替换掉之前该原子对象封装的值并返回之前该原子对象封装的值整个过程是原子的(因此exchange 操作也称为read-modify-write操作)。该函数与 std::atomic 对象的atomic::exchange() 成员函数等价。atomic_exchange_explicittemplate (1)template class T T atomic_store_explicit (volatile atomicT* obj, T val, memory_order sync) noexcept; template class T T atomic_store_explicit (atomicT* obj, T val, memory_order sync) noexcept;overloads (2)T atomic_store_explicit (volatile A* obj, T val, memory_order sync) noexcept; T atomic_store_explicit (A* obj, T val, memory_order sync) noexcept;读取并修改被封装的值exchange 会将 val 指定的值替换掉之前该原子对象封装的值并返回之前该原子对象封装的值整个过程是原子的(因此exchange 操作也称为read-modify-write操作)。sync参数指定内存序(Memory Order)可能的取值如下Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_compare_exchange_weaktemplate (1)template class T bool atomic_compare_exchange_weak (volatile atomicT* obj, T* expected, T val) noexcept; template class T bool atomic_compare_exchange_weak (atomicT* obj, T* expected, T val) noexcept;overloads (2)bool atomic_compare_exchange_weak (volatile A* obj, T* expected, T val) noexcept; bool atomic_compare_exchange_weak (A* obj, T* expected, T val) noexcept;比较并交换被封装的值(weak)与参数 expected 所指定的值是否相等如果相等则用 val 替换原子对象的旧值。不相等则用原子对象的旧值替换expected因此调用该函数之后如果被该原子对象封装的值与参数 expected 所指定的值不相等expected中的内容就是原子对象的旧值。该函数通常会读取原子对象封装的值如果比较为 true(即原子对象的值等于expected)则替换原子对象的旧值但整个操作是原子的在某个线程读取和修改该原子对象时另外的线程不能对读取和修改该原子对象。注意该函数直接比较原子对象所封装的值与参数expected的物理内容所以某些情况下对象的比较操作在使用 operator() 判断时相等但 atomic_compare_exchange_weak 判断时却可能失败因为对象底层的物理内容中可能存在位对齐或其他逻辑表示相同但是物理表示不同的值(比如 true 和 2 或 3它们在逻辑上都表示真但在物理上两者的表示并不相同)。与 atomic_compare_exchange_strong 不同,weak版本的 compare-and-exchange 操作允许(spuriously 地)返回 false(即原子对象所封装的值与参数expected的物理内容相同但却仍然返回 false)不过在某些需要循环操作的算法下这是可以接受的并且在一些平台下 compare_exchange_weak 的性能更好 。如果 atomic_compare_exchange_weak 的判断确实发生了伪失败(*spurious failures)——*即使原子对象所封装的值与参数expected的物理内容相同但判断操作的结果却为 falseatomic_compare_exchange_weak 函数返回 false并且参数 expected 的值不会改变。atomic_compare_exchange_weak_explicittemplate (1)template class T bool atomic_compare_exchange_weak_explicit (volatile atomicT* obj, T* expected, T val, memory_order success, memory_order failure) noexcept; template class T bool atomic_compare_exchange_weak_explicit (atomicT* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;overloads (2)bool atomic_compare_exchange_weak_explicit (volatile A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept; bool atomic_compare_exchange_weak_explicit (A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;比较并交换被封装的值(weak)与参数 expected 所指定的值是否相等如果相等则用 val 替换原子对象的旧值。不相等则用原子对象的旧值替换expected因此调用该函数之后如果被该原子对象封装的值与参数 expected 所指定的值不相等expected中的内容就是原子对象的旧值。该函数通常会读取原子对象封装的值如果比较为 true(即原子对象的值等于expected)则替换原子对象的旧值但整个操作是原子的在某个线程读取和修改该原子对象时另外的线程不能对读取和修改该原子对象。 内存序Memory Order的选择取决于比较操作结果如果比较结果为 true(即原子对象的值等于expected)则选择参数 success 指定的内存序否则选择参数 failure 所指定的内存序。注意该函数直接比较原子对象所封装的值与参数expected的物理内容所以某些情况下对象的比较操作在使用 operator() 判断时相等但 compare_exchange_weak 判断时却可能失败因为对象底层的物理内容中可能存在位对齐或其他逻辑表示相同但是物理表示不同的值(比如 true 和 2 或 3它们在逻辑上都表示真但在物理上两者的表示并不相同)。与 atomic_compare_exchange_strong 不同,weak版本的 compare-and-exchange 操作允许(spuriously 地)返回 false(即原子对象所封装的值与参数expected的物理内容相同但却仍然返回 false)不过在某些需要循环操作的算法下这是可以接受的并且在一些平台下 compare_exchange_weak 的性能更好 。如果 atomic_compare_exchange_weak 的判断确实发生了伪失败(*spurious failures)——*即使原子对象所封装的值与参数expected的物理内容相同但判断操作的结果却为 falseatomic_compare_exchange_weak函数返回 false并且参数 expected 的值不会改变。对于某些不需要采用循环操作的算法而言, 通常采用 atomic_compare_exchange_strong 更好。另外该函数的内存序由 sync 参数指定可选条件如下Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_compare_exchange_strongtemplate (1)template class T bool atomic_compare_exchange_strong (volatile atomicT* obj, T* expected, T val) noexcept; template class T bool atomic_compare_exchange_strong (atomicT* obj, T* expected, T val) noexcept;overloads (2)bool atomic_compare_exchange_strong (volatile A* obj, T* expected, T val) noexcept; bool atomic_compare_exchange_strong (A* obj, T* expected, T val) noexcept;比较并交换被封装的值(strong)与参数 expected 所指定的值是否相等如果相等则用 val 替换原子对象的旧值。不相等则用原子对象的旧值替换expected因此调用该函数之后如果被该原子对象封装的值与参数 expected 所指定的值不相等expected中的内容就是原子对象的旧值。该函数通常会读取原子对象封装的值如果比较为 true(即原子对象的值等于expected)则替换原子对象的旧值但整个操作是原子的在某个线程读取和修改该原子对象时另外的线程不能对读取和修改该原子对象。注意该函数直接比较原子对象所封装的值与参数expected的物理内容所以某些情况下对象的比较操作在使用 operator() 判断时相等但 compare_exchange_weak 判断时却可能失败因为对象底层的物理内容中可能存在位对齐或其他逻辑表示相同但是物理表示不同的值(比如 true 和 2 或 3它们在逻辑上都表示真但在物理上两者的表示并不相同)。与 atomic_compare_exchange_weak 不同, strong版本的 compare-and-exchange 操作不允许(spuriously 地)返回 false即原子对象所封装的值与参数expected的物理内容相同比较操作一定会为 true。不过在某些平台下如果算法本身需要循环操作来做检查 atomic_compare_exchange_weak 的性能会更好。因此对于某些不需要采用循环操作的算法而言, 通常采用 atomic_compare_exchange_strong 更好。atomic_compare_exchange_strong_explicittemplate (1)template bool atomic_compare_exchange_strong_explicit (volatile atomic* obj, T* expected, T val, memory_order success, memory_order failure) noexcept; template bool atomic_compare_exchange_strong_explicit (atomic* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;overloads (2)bool atomic_compare_exchange_strong_explicit (volatile A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept; bool atomic_compare_exchange_strong_explicit (A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;比较并交换被封装的值(strong)与参数 expected 所指定的值是否相等如果相等则用 val 替换原子对象的旧值。不相等则用原子对象的旧值替换expected因此调用该函数之后如果被该原子对象封装的值与参数 expected 所指定的值不相等expected中的内容就是原子对象的旧值。该函数通常会读取原子对象封装的值如果比较为 true(即原子对象的值等于expected)则替换原子对象的旧值但整个操作是原子的在某个线程读取和修改该原子对象时另外的线程不能对读取和修改该原子对象。 内存序Memory Order的选择取决于比较操作结果如果比较结果为 true(即原子对象的值等于expected)则选择参数 success 指定的内存序否则选择参数 failure 所指定的内存序。注意该函数直接比较原子对象所封装的值与参数expected的物理内容所以某些情况下对象的比较操作在使用 operator() 判断时相等但 compare_exchange_weak 判断时却可能失败因为对象底层的物理内容中可能存在位对齐或其他逻辑表示相同但是物理表示不同的值(比如 true 和 2 或 3它们在逻辑上都表示真但在物理上两者的表示并不相同)。与atomic_compare_exchange_weak 不同, strong版本的 compare-and-exchange 操作不允许(spuriously 地)返回 false即原子对象所封装的值与参数expected的物理内容相同比较操作一定会为 true。不过在某些平台下如果算法本身需要循环操作来做检查 atomic_compare_exchange_weak 的性能会更好。因此对于某些不需要采用循环操作的算法而言, 通常采用 atomic_compare_exchange_strong 更好。另外该函数的内存序由 sync 参数指定可选条件如下Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_fetch_addtemplate (integral) (1)template class T T atomic_fetch_add (volatile atomicT* obj, T val) noexcept; template class T T atomic_fetch_add (atomicT* obj, T val) noexcept;template (pointer) (2)template class U U* atomic_fetch_add (volatile atomicU** obj, ptrdiff_t val) noexcept; template class U U* atomic_fetch_add (atomicU** obj, ptrdiff_t val) noexcept;overloads (3)T atomic_fetch_add (volatile A* obj, M val) noexcept; T atomic_fetch_add (A* obj, M val) noexcept;将原子对象的封装值加 val并返回原子对象的旧值适用于整形和指针类型的 std::atomic 特化版本整个过程是原子的。该函数默认内存序为 memory_order_seq_cst。该函数等价于 std::atomic 对象的atomic::fetch_add和 atomic::operator 成员函数。atomic_fetch_add_explicittemplate (integral) (1)template class T T atomic_fetch_add_explicit (volatile atomicT* obj, T val, memory_order sync) noexcept; template class T T atomic_fetch_add_explicit (atomicT* obj, T val, memory_order sync) noexcept;template (pointer) (2)template class U U* atomic_fetch_add_explicit (volatile atomicU** obj, ptrdiff_t val, memory_order sync) noexcept; template class U U* atomic_fetch_add_explicit (atomicU** obj, ptrdiff_t val, memory_order sync) noexcept;overloads (3)T atomic_fetch_add_explicit (volatile A* obj, M val, memory_order sync) noexcept; T atomic_fetch_add_explicit (A* obj, M val, memory_order sync) noexcept;将原子对象的封装值加 val并返回原子对象的旧值适用于整形和指针类型的 std::atomic 特化版本整个过程是原子的。该函数等价于 std::atomic 对象的atomic::fetch_add成员函数。sync 参数指定内存序Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_fetch_subtemplate (integral) (1)template class T T atomic_fetch_sub (volatile atomicT* obj, T val) noexcept; template class T T atomic_fetch_sub (atomicT* obj, T val) noexcept;template (pointer) (2)template class U U* atomic_fetch_sub (volatile atomicU** obj, ptrdiff_t val) noexcept; template class U U* atomic_fetch_sub (atomicU** obj, ptrdiff_t val) noexcept;overloads (3)T atomic_fetch_sub (volatile A* obj, M val) noexcept; T atomic_fetch_sub (A* obj, M val) noexcept;将原子对象的封装值减 val并返回原子对象的旧值适用于整形和指针类型的 std::atomic 特化版本整个过程是原子的。atomic_fetch_sub_explicittemplate (integral) (1)template class T T atomic_fetch_sub_explicit (volatile atomicT* obj, T val, memory_order sync) noexcept; template class T T atomic_fetch_sub_explicit (atomicT* obj, T val, memory_order sync) noexcept;template (pointer) (2)template class U U* atomic_fetch_sub_explicit (volatile atomicU** obj, ptrdiff_t val, memory_order sync) noexcept; template class U U* atomic_fetch_sub_explicit (atomicU** obj, ptrdiff_t val, memory_order sync) noexcept;overloads (3)T atomic_fetch_sub_explicit (volatile A* obj, M val, memory_order sync) noexcept; T atomic_fetch_sub_explicit (A* obj, M val, memory_order sync) noexcept;将原子对象的封装值减 val并返回原子对象的旧值适用于整形和指针类型的 std::atomic 特化版本整个过程是原子的。该函数等价于 std::atomic 对象的atomic::fetch_sub成员函数。sync 参数指定内存序Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_fetch_andemplate (integral) (1)template class T T atomic_fetch_and (volatile atomicT* obj, T val) noexcept; template class T T atomic_fetch_and (atomicT* obj, T val) noexcept;overloads (2)T atomic_fetch_and (volatile A* obj, T val) noexcept; T atomic_fetch_and (A* obj, T val) noexcept;将原子对象的封装值按位与 val并返回原子对象的旧值只适用于整型的 std::atomic 特化版本整个过程是原子的。atomic_fetch_and_explicittemplate (integral) (1)template class T T atomic_fetch_and_explicit (volatile atomicT* obj, T val, memory_order sync) noexcept; template class T T atomic_fetch_and_explicit (atomicT* obj, T val, memory_order sync) noexcept;overloads (2)T atomic_fetch_and_explicit (volatile A* obj, T val, memory_order sync) noexcept; T atomic_fetch_and_explicit (A* obj, T val, memory_order sync) noexcept;将原子对象的封装值按位与 val并返回原子对象的旧值只适用于整型的 std::atomic 特化版本整个过程是原子的。该函数等价于 std::atomic 对象的atomic::fetch_and成员函数。sync 参数指定内存序Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_fetch_ortemplate (integral) (1)template class T T atomic_fetch_or (volatile atomicT* obj, T val) noexcept; template class T T atomic_fetch_or (atomicT* obj, T val) noexcept;overloads (2)T atomic_fetch_or (volatile A* obj, T val) noexcept; T atomic_fetch_or (A* obj, T val) noexcept;将原子对象的封装值按位或 val并返回原子对象的旧值只适用于整型的 std::atomic 特化版本整个过程是原子的。atomic_fetch_or_explicittemplate (integral) (1)template class T T atomic_fetch_or_explicit (volatile atomicT* obj, T val, memory_order sync) noexcept; template class T T atomic_fetch_or_explicit (atomicT* obj, T val, memory_order sync) noexcept;overloads (2)T atomic_fetch_or_explicit (volatile A* obj, T val, memory_order sync) noexcept; T atomic_fetch_or_explicit (A* obj, T val, memory_order sync) noexcept;A将原子对象的封装值按位或 val并返回原子对象的旧值只适用于整型的 std::atomic 特化版本整个过程是原子的。该函数等价于 std::atomic 对象的atomic::fetch_or成员函数。sync 参数指定内存序Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistentatomic_fetch_xortemplate (integral) (1)template class T T atomic_fetch_xor (volatile atomicT* obj, T val) noexcept; template class T T atomic_fetch_xor (atomicT* obj, T val) noexcept;overloads (2)T atomic_fetch_xor (volatile A* obj, T val) noexcept; T atomic_fetch_xor (A* obj, T val) noexcept;将原子对象的封装值按位异或 val并返回原子对象的旧值只适用于整型的 std::atomic 特化版本整个过程是原子的。atomic_fetch_xor_explicittemplate (integral) (1)template class T T atomic_fetch_xor_explicit (volatile atomicT* obj, T val, memory_order sync) noexcept; template class T T atomic_fetch_xor_explicit (atomicT* obj, T val, memory_order sync) noexcept;overloads (2)T atomic_fetch_xor_explicit (volatile A* obj, T val, memory_order sync) noexcept; T atomic_fetch_xor_explicit (A* obj, T val, memory_order sync) noexcept;将原子对象的封装值按位异或 val并返回原子对象的旧值只适用于整型的 std::atomic 特化版本整个过程是原子的。该函数等价于 std::atomic 对象的atomic::fetch_xor成员函数。sync 参数指定内存序Memory Order 值Memory Order 类型memory_order_relaxedRelaxedmemory_order_consumeConsumememory_order_acquireAcquirememory_order_releaseReleasememory_order_acq_relAcquire/Releasememory_order_seq_cstSequentially consistent与原子对象初始化相关的宏此外还有两个宏值得关注他们分别是ATOMIC_VAR_INIT(val)初始化 std::atomic 对象。ATOMIC_FLAG_INIT初始化 std::atomic_flag 对象。