C ++ 11提供了thread-safe initialization of static variables等功能,并引用了我们会说的问题:
Logger& g_logger() {
static Logger lg;
return lg;
}
表面上看(?)无论使用C ++ 11编译器编译的模块是否包含线程头,或者是否在其体内生成任何线程,都是如此。即使它与另一个使用C ++ 11线程并调用该函数的模块相关联,也可以获得保证。
但是如果调用此代码的“其他模块”没有使用C ++ 11线程,而是像Qt的QThread
那样。静态的原子初始化是否超出了C ++ 11的范围,能够做出这样的保证?或者仅使用C ++ 11编译模块然后与其他C ++ 11代码链接的事实是否意味着您将获得保证?
有没有人知道这样的问题的好参考?
答案 0 :(得分:7)
有没有人知道这样的问题的好参考?
不确定。 C ++标准。它描述了C ++代码的行为。如果您的库是C ++代码,则需要遵循此行为。所以,是的,你得到了同样的保证,好像它是你自己的代码一样。
编译器/运行时/操作系统/其他所有内容是如何解决它的不是你的问题。 C ++标准保证它得到妥善处理。
答案 1 :(得分:4)
您的示例依赖于内存模型,而不是线程的实现方式。执行此代码的人将执行相同的指令。如果两个或多个内核执行此代码,则它们将遵循内存模型。
基本实现等同于:
std::mutex mtx;
Logger * lg = 0;
Logger& g_logger() {
std::unique_lock<std::mutex> lck(mtx);
if (lg == 0)
lg = new Logger;
return *lg;
}
可以优化此代码以使用双重检查锁定模式(DCLP),其在特定处理器体系结构(例如,在x86上)可能快得多。此外,因为编译器生成了这个代码,所以它不会做出疯狂的优化来打破天真的DCLP。