背景

碰到下面一段代码:

“`
new_quota = left_quota >= min_quota_ ? left_quota : left_quota + ;
std::atomic<int64_t> remain_quota_;
remain_quota_.compare_exchange_weak(left_quota, new_quota)

“`
compare_exchange_weak 不太熟悉啊,于是查查cpp.plus。

分析

compare_exchange_weak和compare_exchange_strong则是著名的CAS(compare and set)。参数会要求在这里传入期待的数值和新的数值。它们对比变量的值和期待的值是否一致,如果是,则替换为用户指定的一个新的数值。如果不是,则将变量的值和期待的值交换。

weak版本的CAS允许偶然出乎意料的返回(比如在字段值和期待值一样的时候却返回了false),不过在一些循环算法中,这是可以接受的。通常它比起strong有更高的性能。

那么这就需要理解compare_exchange_weak的具体用法:

exchange允许2个数值进行交换,并保证整个过程是原子的。

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的memory order。

功能

当前值与期望值相等时,修改当前值为设定值,返回true
当前值与期望值不等时,将期望值修改为当前值,返回false
这个函数可能在满足true的情况下仍然返回false,所以只能在循环里使用,否则可以使用它的strong版本

## 返回值
true: 和expected 相等然后和desired value相交换;
false: 和 expected 不等,不更新;
## memory order
(没太理解为啥必须是 acq rel?)

拓展

这个CAS应用很广泛,比如下面的无锁入栈:

5   std::atomic<node*> head;
16 public:
17   void push(T const& data)
18   {
19     node* const new_node=new node(data); 
20     new_node->next=head.load(); 
21     while(!head.compare_exchange_weak(new_node->next,new_node));
22   }