【发布时间】:2018-05-31 23:19:15
【问题描述】:
我对@987654322@ 的用途有点困惑。需要明确的是,我完全了解std::call_once 做什么,以及如何使用它。它通常用于原子地初始化某个状态,并确保只有一个线程初始化该状态。我还在网上看到许多尝试使用std::call_once 创建线程安全的单例。
作为 demonstrated here,假设您编写了一个线程安全的单例,如下所示:
CSingleton& CSingleton::GetInstance()
{
std::call_once(m_onceFlag, [] {
m_instance.reset(new CSingleton);
});
return *m_instance.get();
}
好的,我明白了。但我认为std::call_once 唯一真正保证的是传递的函数将仅执行一次。但它是否也保证如果多个线程之间存在调用函数的竞赛,并且一个线程获胜,其他线程将阻塞直到获胜的线程从打电话?
因为如果是这样,我认为call_once 和普通同步互斥锁之间没有区别,例如:
CSingleton& CSingleton::GetInstance()
{
std::unique_lock<std::mutex> lock(m_mutex);
if (!m_instance)
{
m_instance.reset(new CSingleton);
}
lock.unlock();
return *m_instance;
}
那么,如果std::call_once 确实强制其他线程阻塞,那么std::call_once 相对于常规互斥体有什么好处?再想一想,std::call_once 肯定不得不 强制其他线程阻塞,否则在用户提供的函数中完成的任何计算都不会同步。再说一遍,std::call_once 在普通互斥体之上提供了什么?
【问题讨论】:
-
你试过/测试了吗?
-
@Brandon,测试竞争条件可能不切实际。
-
为什么在第二个示例中调用
lock.unlock()?
标签: c++ multithreading c++11