5.2.3 std::atomic
最基本的内置类型就是std::atomic
std::atomic b(true);
b=false;
相比于atomic_flog,test_and_set()函数被替换成exchange(),设置新的值,返回旧的值。想获取其值既可以使用load(),也可以隐式的转换。同样,想设置它的值,既可以使用store()函数也可以使用隐式转换。
atomic
根据当前值决定是否存储新的值
这种操作叫做“比较/交换”,有两个这样的成员函数:compare_exchange_weak()、compare_exchange_strong()。
compare_exchange_weak()的一个函数声明是:
bool atomic::compare_exchange_weak( bool& expected_value, bool new_value, memory_order _Order) noexcept;
参数expected_value代表在执行这个函数之前的一个期待值,或者说预测值。
函数首先比较atomic
对于compare_exchange_weak()函数来说,即使expected_value的值与atomic
根据www.cplusplus.com的描述:On these spurious failures, the function returns false
while not modifying expected.
如果出现虚假失败,这个函数返回false,并且没有修改expected参数。
因为compare_exchange_weak()可能出现虚假失败,因此必须使用循环调用的方式:
bool expected=false;
extern atomic b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);
如果是真的失败,那么compare_exchange_weak()的返回值应该是false、并且expected的值应该是true,那么循环就终止了。除非compare_exchange_weak()的返回值是false,但expected的值依然是false,这明显代表是假失败,因此循环将继续。
另一个函数compare_exchange_strong()则不同,它保证只有std::atomic
如果你无论如何都想更新当前原子变量的值(或许想更新为一个依赖当前值的新值),那么就需要每次更新expected的值。如果此时没有其他线程在修改原子变量,那么compare_exchange_weak()和compare_exchange_strong()两个函数都能保证在循环时执行成功。如果获取expected值的耗时很小,那么循环使用compare_exchange_weak()是个好的选择;如果获取expected值的耗时很大,那么如果expected的值没有改变的话,使用compare_exchange_strong()更好,因为它不需要重新获取expected的值。对于 std::atomic
比较/交换操作可以接受两个内存指令参数,它们用指定执行成功或失败时使用的内存指令。比较完美的调用是,成功时使用memory_order_acq_rel指令,失败时使用memory_order_relaxed指令。一次失败的操作并没有对原子对象执行保存操作,因此不能使用memory_order_release或memory_order_acq_rel指令。你也不能为执行失败提供比执行成功更为严格的内存指令,例如,如果你想给执行失败时指定memory_order_acquire或memory_order_seq_cst指令,那么你必须给执行成功时指定同样的指令。
std::atomic