任何 C++11 线程安全保证是不是适用于使用 C++11 编译/链接的第三方线程库?
Posted
技术标签:
【中文标题】任何 C++11 线程安全保证是不是适用于使用 C++11 编译/链接的第三方线程库?【英文标题】:Do any C++11 thread-safety guarantees apply to third-party thread libraries compiled/linked with C++11?任何 C++11 线程安全保证是否适用于使用 C++11 编译/链接的第三方线程库? 【发布时间】:2012-03-07 20:03:29 【问题描述】: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 代码这一事实是否意味着无论如何你都会得到保证?
有没有人知道涵盖此类问题的良好参考资料?
【问题讨论】:
静态初始化是一种语言属性。我看不出这会如何受到特定库的影响。 @pmr 这对我来说似乎有点棘手,因为 - 例如 - 上述静态的内存是在程序开始时分配的,但是构造函数第一次运行函数时使用它内部的静态被调用。要实现这一点,似乎需要对底层线程模型的全知,所以我怀疑如果混合 QThread/C++11thread 是否能正确... . @HostileFork:只要(c++ 和 qt)都使用相同的操作系统工具进行线程处理,我看不出有什么地方会出错。我也不明白为什么两者都不应该使用操作系统线程工具。 虽然底层线程模型是已知的。 QThreads 只是一个包装器。它们在 C++ 库中实现,因此它们的行为就像 C++ 所说的线程应该行为。 C++ 标准描述了“执行线程”。它并不是说必须将它们创建为std::thread
对象。 pthread、Boost.Thread 和 QThread 都是根据 C++11 执行的有效线程
【参考方案1】:
有没有人知道涵盖此类问题的良好参考资料?
当然。 C++ 标准。它描述了 C++ 代码的行为。如果您的库是 C++ 代码,则需要遵循此行为。所以是的,您得到的保证与您自己的代码一样。
编译器/运行时/操作系统/其他所有东西的确切方式不是你的问题。 C++ 标准保证它得到照顾。
【讨论】:
点了。然而,无论这是否是我的问题,我都想知道我是否使用 GCC 和 Qt 是否能“成功”。从技术的角度来看,如果将 C++03static.a
库链接到 C++11 icallthestatic
可执行文件,则链接器不太可能做到这一点。但这指向了一个更广泛的问题,即“您可能无法将 C++03 代码与 C++11 链接并获得系统的 C++11 保证”......
C++03 代码只保证表现得像 C++03。因此,如果您链接到 C++03 库,则不能指望它实现仅由 C++11 提供的保证【参考方案2】:
您的示例依赖于内存模型,而不是线程的实现方式。执行此代码的人将执行相同的指令。如果两个或更多内核执行此代码,它们将遵循内存模型。
基本的实现是这样的:
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。
【讨论】:
酷,谢谢...看来大家一致认为这是应该是安全的。仅供参考:我研究它的原因是为了解决这种情况......***.com/questions/9507973/…以上是关于任何 C++11 线程安全保证是不是适用于使用 C++11 编译/链接的第三方线程库?的主要内容,如果未能解决你的问题,请参考以下文章
C++11:基于std::queue和std::mutex构建一个线程安全的队列