首页 > 解决方案 > cppreference.com 上 c++20 的奇怪 atomic_flag 示例

问题描述

cppreference.com std::atomic_flag列出了先前 c++20 和 c++20 中的两个自旋锁示例。最后修改日期为 2020 年 7 月 21 日 12:58。

之前的 c++20:

#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
 
std::atomic_flag lock = ATOMIC_FLAG_INIT;
 
void f(int n)
{
    for (int cnt = 0; cnt < 100; ++cnt) {
        while (lock.test_and_set(std::memory_order_acquire))  // acquire lock
             ; // spin
        std::cout << "Output from thread " << n << '\n';
        lock.clear(std::memory_order_release);               // release lock
    }
}
 
int main()
{
    std::vector<std::thread> v;
    for (int n = 0; n < 10; ++n) {
        v.emplace_back(f, n);
    }
    for (auto& t : v) {
        t.join();
    }
}

C++ 20:

#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
 
std::atomic_flag lock = ATOMIC_FLAG_INIT;
 
void f(int n)
{
    for (int cnt = 0; cnt < 100; ++cnt) {
        while (lock.test_and_set(std::memory_order_acquire))  // acquire lock
             while (lock.test(std::memory_order_relaxed))     // test lock
                 ; // spin
        std::cout << "Output from thread " << n << '\n';
        lock.clear(std::memory_order_release);                // release lock
    }
}
 
int main()
{
    std::vector<std::thread> v;
    for (int n = 0; n < 10; ++n) {
        v.emplace_back(f, n);
    }
    for (auto& t : v) {
        t.join();
    }
}

在 c++20 示例中困扰我的两件事是:

(1) ATOMIC_FLAG_INIT 在 c++20 中已弃用,默认构造函数应为我们存储值为 false。

(2)在标志设置为 true 之后引入的“优化”while (lock.test(std::memory_order_relaxed)) 对我来说没有意义。在那种情况下不应该while (lock.test(std::memory_order_relaxed)) 总是立即返回吗?那么为什么它是对前面的 c++20 示例的优化呢?

编辑:c++20 为 atomic 引入了 test(),它只是通过执行原子加载来检查标志是否为真。当 test_and_set() 失败时,它被放置在内部循环中,以便计算机在第二次返回 test_and_set() 之前首先在 test() while 循环内旋转。

标签: c++

解决方案


见评论:

该编辑来自stackoverflow.com/q/62318642/2945027 – Cubbi


推荐阅读