是否有任何C ++ 11线程安全保证适用于使用C ++ 11编译/链接的第三方线程库?

时间:2012-03-07 20:03:30

标签: c++ thread-safety c++11 language-lawyer

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代码链接的事实是否意味着您将获得保证?

有没有人知道这样的问题的好参考?

2 个答案:

答案 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。