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

hog*_*iux 11 c++ windows multithreading boost boost-build

我不完全确定threading=multi在构建boost时旗帜到底是什么.文件说:

 Causes the produced binaries to be thread-safe. This requires proper
 support in the source code itself.
Run Code Online (Sandbox Code Playgroud)

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

更多细节:

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

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

我试过建设提升既threading=multithreading=single和似乎都工作,但我真的很想知道我在这里做.

Bee*_*ope 16

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

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

在过去,类似的参数或stdlib风格可供C和C++ std库提供我的编译器,尽管今天大多数只是多线程版本可用.

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的回复.

  • @hogliux我建议你不要相信任何人,但只是自己测试一下,就像我刚刚做的那样:).制作一个虚拟测试和阻塞文件,就像Joaquin在上述链接中描述的那样,并查看为threading = single定义了哪些宏.另外,请参阅`boost/config/suffix.hpp`. (2认同)

Igo*_* R. 5

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

使用gcc threading=multi 只是暗示#define BOOST_HAS_PTHREADS,而使用MSVC它不会产生任何可见效果.特别地,_MTthreading=singlethreading=multi模式中定义.

然而,注意,一个可以显式地通过定义适当的宏,如配置单线程模式Boost库BOOST_SP_DISABLE_THREADS,BOOST_ASIO_DISABLE_THREADS或全局带BOOST_DISABLE_THREADS.