atomic_flag atomic_flag 一种简单的原子布尔类型,只支持两种操作,test-and-set 和 clear
1. test表示先测试(读取当前atomic_flag的值)并返回个这结果值;
2. set表示将atomic_flag状态设置为ture。
3. 初始状态c++20之前不确定 ,c++20之后是false
4.ATOMIC_FLAG_INIT: 如果某个 std::atomic_flag 对象使用该宏初始化,那么可以保证该 std::atomic_flag 对象在创建时处于 clear 状态。
std::atomic_flag lock_stream = ATOMIC_FLAG_INIT;
5.test_and_set() 函数检查 std::atomic_flag 标志,如果 std::atomic_flag 之前没有被设置过,则设置 std::atomic_flag 的标志,并返回先前该 std::atomic_flag 对象是否被设置过(true or false ,有可能原本就是true如果之前 std::atomic_flag 对象已被设置,则返回 true,否则返回 false。)
m_isNotStop.test_and_set();
6.std::atomic_flag::clear() 清除 std::atomic_flag 标志使得下一次调用 std::atomic_flag::test_and_set 返回 false。
7. c++20以前只提供了上面两个方法
8. is_lock_free 返回true 支持无锁
总得来说,有下面五个通用方法
store // 原子写操作
load // 对应的原子读操作。
exchange // 允许2个数值进行交换,并保证整个过程是原子的。
compare_exchange_weak //
compare_exchange_strong //
// 而compare_exchange_weak和compare_exchange_strong则是著名的CAS(compare and set)。参数会要求在这里传入期待的数值和新的数值。它们对比变量的值和期待的值是否一致,如果是,则替换为用户指定的一个新的数值 返回true。如果不是,那么期待值(expected)将被更新为原子变量的当前值。 返回false
/*
compare_exchange_strong:atomic库中的一个函数,入参是3个,expect,desire,memoryorder,意思是如果当前的变
量this的值==expect值,则将this值改为desire,并返回true,否则,返回false,不进行修改,即进行一个读的操作。通常用于例如线程B等待线程A执行完毕,或者执行到某个步骤。此时线程B可以进行while等待,线程A在执行到对应步骤,将对应的原子变量置为expect值即可。类似于“接力运动”。这里由于会进行读写操作,所以,memory order一般是acq rel,而A线程由于要保证都执行完毕,执行顺序没有关系,所以一般是Release的
weak版和strong版的区别:
weak版本的CAS允许偶然出乎意料的返回(比如在字段值和期待值一样的时候却返回了false),不过在一些循环算法中,这是可以接受的。通常它比起strong有更高的性能。
bool compare_exchange_weak(T& expected, T desired, std::memory_order success, std::memory_order failure);
为什么有两个内存序参数?
-
成功内存序参数 (
success
):- 当
compare_exchange_weak
成功时,需要保证新值对其他线程可见,这通常需要较强的内存序。例如,我们可能希望在交换成功后发布一个存储顺序(std::memory_order_release
)或更强的顺序(如std::memory_order_acq_rel
或std::memory_order_seq_cst
)。
- 当
-
失败内存序参数 (
failure
):- 当
compare_exchange_weak
失败时,不需要发布新值,但仍需要保持某种内存顺序以确保读取预期值的正确性。通常这会是一个较弱的序列,例如std::memory_order_relaxed
或std::memory_order_acquire
。
- 当
#include <atomic>
int main(int argc, char ** argv)
{
std::atomic<int> counter(1);
int expected = 3;
bool success = counter.compare_exchange_weak(expected, 1);
if (success)
{
// 交换成功,counter现在是1,expected现在是1(因为它被更新了)
printf("true: %d %d\n", success, counter.load());
}
else
{
// 交换失败,counter的值不是0,expected现在是counter的当前值
printf("false: %d %d %d\n", success, counter.load(), expected);
}
}
at