没有真正理解 std::atomic::compare_exchange_weak 和compare_exchange_strong 的逻辑

Bru*_*ice 4 c++ multithreading atomic compare-and-swap stdatomic

我读过https://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange

以原子方式将 *this 的对象表示形式 (C++20 之前) 值表示形式 (C++20 起) 与预期的表示形式进行比较,如果它们按位相等,则将前者替换为所需的(执行读取-修改-写入操作) )。否则,将 *this 中存储的实际值加载到预期中(执行加载操作)。

据我了解,代码如下

bool expected=true;
extern atomic<bool> b = false; 
void foo ()
{
//
    while(!b.compare_exchange_weak(expected, false));
//
}
Run Code Online (Sandbox Code Playgroud)

循环运行一次后(忽略虚假失败)它将失败,并将写入预期false,因此在第二次迭代时,compare_exchange_weak将返回成功,尽管b尚未更改为true。但这一切有什么意义呢?我虽然可以用它作为同步锁,等待其他线程更改b,但现在我想不出它的用法。

cppreference 中的示例还表明,两次调用compare_exchange_strong 后将会成功。

#include <atomic>
#include <iostream>
 
std::atomic<int>  ai;
 
int  tst_val= 4;
int  new_val= 5;
bool exchanged= false;
 
void valsout()
{
    std::cout << "ai= " << ai
          << "  tst_val= " << tst_val
          << "  new_val= " << new_val
          << "  exchanged= " << std::boolalpha << exchanged
          << "\n";
}
 
int main()
{
    ai= 3;
    valsout();
 
    // tst_val != ai   ==>  tst_val is modified
    exchanged= ai.compare_exchange_strong( tst_val, new_val );
    valsout();
 
    // tst_val == ai   ==>  ai is modified
    exchanged= ai.compare_exchange_strong( tst_val, new_val );
    valsout();
}
Run Code Online (Sandbox Code Playgroud)

结果:

ai= 3  tst_val= 4  new_val= 5  exchanged= false
ai= 3  tst_val= 3  new_val= 5  exchanged= false
ai= 5  tst_val= 3  new_val= 5  exchanged= true
Run Code Online (Sandbox Code Playgroud)

Dre*_*ann 5

std::atomic::compare_exchange_weak以线程感知的方式执行此英语任务:

因为变量成立expected,所以它现在应该成立desired

作为一项微不足道的任务,想象一下您的价值std::atomic<int> x应该平方。但其他线程可能正在修改它,因此您不能简单地读取该值,对其求平方并将新值写回。读完后数值可能会改变!

这是执行此任务的线程安全方法。您可以保证存储的值将被替换为它的平方。

int expected = x;
while( !x.compare_exchange_weak(expected, expected*expected) );
Run Code Online (Sandbox Code Playgroud)

除非该值已更改,否则此代码将自动替换expected为其平方。

如果该值已更改,expected则现在使用新值进行更新,并且代码会再次尝试。