c++ - std::call_once 是免费的吗?

标签 c++ multithreading c++11 lock-free

我想知道 std::call_once 锁是否空闲。 There是使用互斥锁的 call_once 实现。但是我们为什么要使用互斥体呢?我尝试使用 atomic_bool 和 CAS 操作编写简单的实现。代码线程安全吗?

#include <iostream>
#include <thread>
#include <atomic>
#include <unistd.h>

using namespace std;
using my_once_flag = atomic<bool>;

void my_call_once(my_once_flag& flag, std::function<void()> foo) {
    bool expected = false;
    bool res = flag.compare_exchange_strong(expected, true,
                                            std::memory_order_release, std::memory_order_relaxed);
    if(res)
        foo();
}
my_once_flag flag;
void printOnce() {
    usleep(100);
    my_call_once(flag, [](){
       cout << "test" << endl;
    });
}

int main() {
    for(int i = 0; i< 500; ++i){
            thread([](){
                printOnce();
            }).detach();
    }
    return 0;
} 

最佳答案

您建议的实现不是线程安全的。它确实保证 foo() 只会通过这段代码被调用一次,但它不保证所有线程都会看到调用 foo() 的副作用。假设线程 1 执行比较并得到 true,然后调度程序切换到线程 2,然后线程 2 调用 foo()。线程 2 将得到 false,跳过对 foo() 的调用,然后继续。由于尚未执行对 foo() 的调用,线程 2 可以在 foo() 的任何副作用发生之前继续执行。

关于c++ - std::call_once 是免费的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40707149/

相关文章:

c++ - 优化 VS2010 c++ 中的方法调用(多线程)

c++ - 使用 PIMPL 惯用语为可复制类编写可复制的 unique_ptr

c++ - 用 gcc 编译 asio

c++ - 程序无法在其他 Windows 机器上正常运行

C - 函数的隐式声明 "pthread_timedjoin_np"

c++ - 有没有办法将 std::array 与文字或初始值设定项列表一起用于比较,就像赋值一样?

qt - Qt5 中仍然需要 "public slots:"部分吗?

c++ - 初始化稀疏静态数组

c++ - C++ 中的命名空间类模板继承

java - 两个线程通过同步方法访问队列;一个可以严格优先于另一个吗?