当前位置: 首页 > 工具软件 > Atomic > 使用案例 >

c++ 11 原子操作库 (std::atomic)(三)

戎元忠
2023-12-01
定义于头文件 <atomic>

atomic 类模板及其针对布尔、整型和指针类型的特化

每个 std::atomic 模板的实例化和全特化定义一个原子类型。若一个线程写入原子对象,同时另一线程从它读取,则行为良好定义(数据竞争的细节见内存模型)。

另外,对原子对象的访问可以建立线程间同步,并按 std::memory_order 所对非原子内存访问定序。

std::atomic 既不可复制亦不可移动。

令原子值增加或减少一

std::atomic<T>::operator++,++(int),--,--(int)

T operator++() noexcept;
T operator++() volatile noexcept;

(1)(仅为 atomic<Integral> 模板特化的成员)
(C++11 起)

T* operator++() noexcept;
T* operator++() volatile noexcept;

(1)(仅为 atomic<T*> 模板特化的成员)
(C++11 起)

T operator++( int ) noexcept;
T operator++( int ) volatile noexcept;

(2)(仅为 atomic<Integral> 模板特化的成员)
(C++11 起)

T* operator++( int ) noexcept;
T* operator++( int ) volatile noexcept;

(2)(仅为 atomic<T*> 模板特化的成员)
(C++11 起)

T operator--() noexcept;
T operator--() volatile noexcept;

(3)(仅为 atomic<Integral> 模板特化的成员)
(C++11 起)

T* operator--() noexcept;
T* operator--() volatile noexcept;

(3)(仅为 atomic<T*> 模板特化的成员)
(C++11 起)

T operator--( int ) noexcept;
T operator--( int ) volatile noexcept;

(4)(仅为 atomic<Integral> 模板特化的成员)
(C++11 起)

T* operator--( int ) noexcept;
T* operator--( int ) volatile noexcept;

(4)(仅为 atomic<T*> 模板特化的成员)
(C++11 起)

原子地自增或自减当前值。操作为读-修改-写操作。

1) 进行原子前自增。等价于 fetch_add(1)+1 。

2) 进行原子后自增。等价于 fetch_add(1) 。

3) 进行原子前自减。等价于 fetch_sub(1)-1 。

4) 进行原子后自减。等价于 fetch_sub(1) 。

对于有符号整数 (Integral) 类型,算术定义为使用补码表示。无未定义结果。对于 T* 类型,结果可能为未定义地址,但这些操作不会另有未定义行为。

参数

(无)

返回值

1,3) 修改后的原子变量的值。正式地说, *this 的修改顺序中自增/自减值的结果立即前趋于此函数的效果。

2,4) 修改前的原子变量的值。正式地说, *this 的修改顺序中值立即前趋于此函数的效果。

注意

不同于大多数前自增和自减运算符,原子类型的前自增和自减运算符不返回被修改对象的引用。它们替而返回存储值的副本。

 

加、减,或与原子值进行逐位与、或、异或

std::atomic<T>::operator+=,-=,&=,|=,^=

仅为 atomic<Integral>(C++11) 与 atomic<Floating>(C++20) 模板特化的成员

T operator+=( T arg ) noexcept;

T operator+=( T arg ) volatile noexcept;

仅为 atomic<T*> 模板特化的成员

T* operator+=( std::ptrdiff_t arg ) noexcept;

T* operator+=( std::ptrdiff_t arg ) volatile noexcept;

仅为 atomic<Integral>(C++11) 与 atomic<Floating>(C++20) 模板特化的成员

T operator-=( T arg ) noexcept;

T operator-=( T arg ) volatile noexcept;

仅为 atomic<T*> 模板特化的成员

T* operator-=( std::ptrdiff_t arg ) noexcept;

T* operator-=( std::ptrdiff_t arg ) volatile noexcept;

仅为 atomic<Integral> 模板特化的成员

T operator&=( T arg ) noexcept;

T operator&=( T arg ) volatile noexcept;

T operator|=( T arg ) noexcept;

T operator|=( T arg ) volatile noexcept;

T operator^=( T arg ) noexcept;

T operator^=( T arg ) volatile noexcept;

 

原子地以涉及先前值和 arg 的计算结果替换当前值。操作是读-修改-写操作。

1) 进行原子加法。等价于 fetch_add(arg) + arg 。

2) 进行原子减法。等价于 fetch_sub(arg) - arg 。

3) 进行原子逐位与。等价于 fetch_and(arg) & arg 。

4) 进行原子逐位或。等价于 fetch_or(arg) | arg 。

5) 进行原子逐位异或。等价于 fetch_xor(arg) ^ arg 。

对于有符号整数 (Integral) 类型,算术定义为使用补码表示。无未定义结果。

对于浮点类型,有影响的浮点环境可能异于调用方线程的浮点环境。操作不必服从对应的 std::numeric_limits 特性,但鼓励这么做。若结果不是其类型所能表示的值,则结果未指定,但操作不会另有未定义行为。

(C++20 起)

对于 T* 类型,结果可能为未定义地址,但操作不会另有未定义行为。若 T 不是对象类型则程序为病式。

参数

arg-算术运算的参数

返回值

返回值(即应用对应二元运算符到 *this 的修改顺序中立即前趋于成员对应函数效果的值)

注意

不同于大多数复合赋值运算符,原子类型的复合赋值运算符不返回到其左侧运算数的引用。它们替而返回存储的值的副本。

原子地将参数加到存储于原子对象的值,并返回先前保有的值

std::atomic<T>::fetch_add

 仅为 atomic<Integral>(C++11) 与 atomic<Floating>(C++20) 模板特化的成员

T fetch_add( T arg,
             std::memory_order order = std::memory_order_seq_cst ) noexcept;

T fetch_add( T arg,
             std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

仅为 atomic<T*> 模板特化的成员

T* fetch_add( std::ptrdiff_t arg,
              std::memory_order order = std::memory_order_seq_cst ) noexcept;

T* fetch_add( std::ptrdiff_t arg,
              std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

原子地以值和 arg 的算术加法结果替换当前值。运算是读修改写操作。按照 order 的值影响内存。

对于有符号 Integral 类型,定义算术为使用补码。无未定义结果。

对于浮点类型,有影响的浮点环境可能异于调用方线程的浮点环境。操作不必服从对应的 std::numeric_limits 特性,但鼓励这么做。若结果不是其类型所能表示的值,则结果未指定,但其他情况下操作无未定义行为。

(C++20 起)

对于 T* 类型,结果可能为未定义的地址,但其他情况下运算无未定义行为。

参数

arg-算术加法的另一参数
order-强制的内存顺序制约

返回值

*this 的修改顺序中,立即前趋此函数效应的值。

调用示例

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<long long> data;
void do_work()
{
    data.fetch_add(1, std::memory_order_relaxed);
}

int main()
{
    std::thread th1(do_work);
    std::thread th2(do_work);
    std::thread th3(do_work);
    std::thread th4(do_work);
    std::thread th5(do_work);

    th1.join();
    th2.join();
    th3.join();
    th4.join();
    th5.join();

    std::cout << "Result:" << data << '\n';
}

 

原子地从存储于原子对象的值减去参数,并获得先前保有的值

std::atomic<T>::fetch_sub

仅为 atomic<Integral>(C++11) 与 atomic<Floating>(C++20) 模板特化的成员

T fetch_sub( T arg,
             std::memory_order order = std::memory_order_seq_cst ) noexcept;

(1)(2)

T fetch_sub( T arg,
             std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

仅为 atomic<T*> 模板特化的成员

T* fetch_sub( std::ptrdiff_t arg,
              std::memory_order order = std::memory_order_seq_cst ) noexcept;

T* fetch_sub( std::ptrdiff_t arg,
              std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

以值和 arg 的算术减法结果原子地替换当前值。操作是读修改写操作。按照 order 的值影响内存。

对于有符号 Integral 类型,定义算术为使用补码表示。无未定义结果。

对于浮点类型,有影响的浮点环境可能异于调用方线程的浮点环境。操作不必服从对应的 std::numeric_limits 特性,但鼓励这么做。若结果不是其类型所能表示的值,则结果未指定,但操作不会另有未定义行为。

(C++20 起)

对于 T* 类型,结果可能是未定义地址,但操作不会另有未定义行为。若 T 不是对象类型则程序为病式。

参数

arg-算术减法的另一参数
order-强制的内存顺序制约

返回值

*this 的修改顺序中立即前趋此函数效果的值。

原子地进行参数和原子对象的值的逐位与,并获得先前保有的值

std::atomic<T>::fetch_and

T fetch_and( T arg,
             std::memory_order order = std::memory_order_seq_cst ) noexcept;

T fetch_and( T arg,
             std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

原子地以值和 arg 逐位与的结果替换当前值。运算是读修改写操作。按照 order 的值影响内存。

参数

arg-逐位与的另一参数
order-强制的内存顺序制约

返回值

*this 的修改顺序中立即前趋此函数效果的值。

原子地进行参数和原子对象的值的逐位或,并获得先前保有的值

std::atomic<T>::fetch_or

T fetch_or( T arg,
            std::memory_order order = std::memory_order_seq_cst ) noexcept;

T fetch_or( T arg,
            std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

原子地以值和 arg 逐位或的结果替换当前值。运算为读修改写操作。按照 order 的值影响内存。

参数

arg-逐位或的另一参数
order-强制的内存顺序制约

返回值

*this 的修改顺序中立即前趋此函数效果的值。

原子地进行参数和原子对象的值的逐位异或,并获得先前保有的值

std::atomic<T>::fetch_xor

T fetch_xor( T arg,
             std::memory_order order = std::memory_order_seq_cst ) noexcept;

T fetch_xor( T arg,
             std::memory_order order = std::memory_order_seq_cst ) volatile noexcept;

原子地以值和 arg 逐位异或的结果替换当前值。运算是读修改写操作。按照 order 的值影响内存。

参数

arg-逐位异或的另一参数
order-强制的内存顺序制约

返回值

*this 的修改顺序中立即前趋此函数效果的值。

 类似资料: