我想知道 std::call_once 锁是否已释放。There https://codereview.stackexchange.com/questions/117468/stdonce-flag-and-stdcall-once-implementation是使用互斥锁的 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 调用之前切换到线程 2foo()
。线程 2 将返回 false,跳过对foo()
,然后继续。自从拨打电话以来foo()
尚未执行,线程 2 可以在产生任何副作用之前继续执行foo()
已经发生。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)