编译boost时,`threading = multi`究竟做了什么?

时间:2013-12-31 15:51:31

标签: c++ windows multithreading boost boost-build

我不完全确定构建boost时threading=multi标志究竟是什么。文档说:

 Causes the produced binaries to be thread-safe. This requires proper
 support in the source code itself.

似乎不是非常具体。这是否意味着对{例如}升级容器的访问受到mutexes/locks或类似的保护?由于我的代码性能至关重要,我想尽量减少任何不必要的互斥量等。

更多细节:

我的代码是一个插件DLL,它被加载到一个多线程的第三方应用程序中。我静态地将boost链接到DLL(除了标准的Windows DLL之外,插件不允许有任何其他依赖项,所以我不得不这样做。)

虽然应用程序是多线程的,但我的DLL中的大多数函数只能从单个线程调用,因此无需保护对容器的访问。我通过使用boost::mutex和朋友明确保护我的代码的剩余位置,可以从多个线程调用。

我尝试使用threading=multithreading=single来构建提升,两者似乎都有效,但我真的很想知道我在这里做了什么。

4 个答案:

答案 0 :(得分:16)

不,threading=multi并不意味着升级容器之类的东西会突然变得安全,无法通过多个线程进行并发访问(从性能的角度来看,这会非常昂贵)。

相反,理论上的意思是将boost编译为线程感知。基本上这意味着当从多个线程访问时,boost方法和类将以合理的默认方式运行,就像std库中的类一样。这意味着您无法从多个线程访问同一对象,除非另有说明,但您可以安全地从多个线程访问不同的对象。即使没有明确的支持,这似乎也很明显,但如果没有受到保护,库使用的任何static状态都会破坏该保证。使用threading=multi可以保证任何此类共享状态都是由互斥锁或其他一些机制保护的属性。

过去类似的参数或stdlib风格可供C和C ++标准库提供我的编译器,虽然现在大多数只是多线程版本可用。

使用threading=multi进行编译可能没什么坏处,因为只需要同步有限数量的静态。你的评论,你的图书馆主要只能由一个线程调用,这并不会激发很多信心 - 毕竟,那些潜在的错误会让你在3点被唤醒经过一夜的长时间饮酒后,你老板上午。

boost的shared_ptr示例提供了丰富的信息。使用threading=single,甚至不能保证从多个线程独立操作两个shared_ptr实例是安全的。如果它们碰巧指向同一个对象(或者,理论上,在一些奇特的实现中,即使它们没有),您将产生未定义的行为,因为共享状态将不会被适当的保护操纵。

使用 threading=multi,这不会发生。但是,从多个线程访问相同的shared_ptr实例仍然不安全。也就是说,它没有给出任何未记录的对象的线程安全保证 - 但它确实给出了独立对象独立的“预期/合理/默认”保证。这个默认的线程安全级别没有一个好名字,但它实际上是当今为多线程语言提供的所有标准库。

最后一点,值得注意的是Boost.Thread隐式总是使用threading=multi编译 - 因为使用boost的多线程类是一个隐含的提示,表明存在多个线程。在没有多线程支持的情况下使用Boost.Thread将是荒谬的。

现在,所有这一切,上面是编译boost“with thread support”或“without thread support”背后的理论思想,这是threading=标志的目的。实际上,由于引入了这个标志,多线程已成为默认,并且单线程异常。实际上,许多默认为单线程行为的编译器和链接器现在默认为多线程 - 或者至少只需要一个“提示”(例如,命令行中存在-pthread)就可以翻转为多线程。

除此之外,还有一个共同的努力,使升级版本“智能” - 因为它应该在环境有利时转换为多线程模式。这很模糊,但必然如此。它变得像弱链接pthreads符号一样复杂,因此使用MT或ST代码的决定实际上推迟到运行时 - 如果pthreads在执行时可用,那些符号将被使用,否则弱链接的存根 - 什么都不做根本 - 将被使用。

底线是threading=multi对于您的场景是正确且无害的,特别是如果您要生成二进制文件,您将分发给其他主机。如果你没有那么特别,那么很可能无论如何都会起作用,因为构建时间甚至是运行时启发式,但你确实有机会默默地使用空存根方法,或者否则使用MT不安全代码。使用正确的选项几乎没有什么缺点 - 但是在这一点的评论中也可以找到一些血腥的细节,以及Igor的回复。

答案 1 :(得分:5)

经过一番挖掘后,事实证明threading=single并没有像人们预期的那样产生太大影响。特别是,它不会影响BOOST_HAS_THREADS宏,因此不会将库配置为采用单线程环境。

使用gcc threading=multi just implies #define BOOST_HAS_PTHREADS,而使用MSVC则不会产生任何可见效果。特别地,_MTthreading=singlethreading=multi模式中定义。

但是请注意,可以通过定义适当的宏来显式配置Boost库以用于单线程模式,例如BOOST_SP_DISABLE_THREADSBOOST_ASIO_DISABLE_THREADS或全局BOOST_DISABLE_THREADS

答案 2 :(得分:2)

让我们简明扼要。 Causes the produced binaries to be thread-safe表示Boost代码适用于不同的线程可以使用不同的Boost对象。这尤其意味着Boost代码将特别关注对可能由Boost库的实现使用的隐藏全局或静态对象的访问的线程安全性。 它不会自动允许不同的线程同时使用相同的Boost对象而没有保护(lock / mutexes /...).

编辑:某些Boost库可能会记录特定函数或类的额外线程安全性。例如,Igor R.在评论中建议的asio::io_service

答案 3 :(得分:0)

文档说明了所需的一切:此选项可确保线程安全。也就是说,在多线程环境中进行编程时,您需要确保某些属性,例如避免不受限制地访问例如变量

我认为,启用此选项是可行的方法。

供进一步参考:BOOST libraries in multithreading-aware mode