问题描述
我不完全确定建设的刺激时,完全线程=多
标志做了什么。文档说:
导致产生的二进制文件是线程安全的。这就需要适当的
支持源$ C $ C本身。
这似乎不是很具体。这是否意味着,例如,提高集装箱的访问是由互斥/锁
或类似把守?正如我的code的性能是至关重要的,我想尽量减少任何不必要的互斥体等。
更多的细节:
我的code是一个插件DLL其中被加载到多线程的第三方应用程序。我静态链接提升到DLL(插件是不允许有除标准的Windows DLL的其他任何依赖关系,因此我不得不这样做)。
虽然,应用程序是多线程的,大部分是在我的DLL功能被永远只从一个单一的线程调用,因此,于通往容器不必加以防护。我用的boost ::互斥
和朋友明确地守护我的code,它可以从多个线程调用,的余缺。
我试过建设提升既线程=多
和线程=单
键,似乎都工作,但我真的很想知道我在这里做什么。
没有,线程=多
并不意味着事情喜欢刺激的容器会突然变得并发安全被多个线程访问(这将是从性能上看昂贵)。
相反,这是什么意思的在理论上的是提升将被编译为线程知道的。基本上,这意味着,升压方法和类将在一个合理的默认方式从多个线程访问时,就像在STD库类表现。这意味着,你不能访问的同一个对象的多个线程,除非另有记载,但您可以从多个线程访问不同的对象,安全。这似乎是显而易见的,即使没有明确的支持,但是任何库使用静态
国家将打破这种保证,如果不受保护。使用线程=多
保证,任何这样的共享状态财产互斥体或其他一些机制把守。
在过去类似的论点或STDLIB味道是可用于C和C ++的std库提供的编译器我,今天虽然大多只是多线程版本。
有可能的小缺点与线程=多编译
的,因为只有静态有限量的需要同步。您的评论你的图书馆将的大多的只能由一个线程调用不会激发了不少信心 - 毕竟,这些都是在3被唤醒了各种潜在的错误,将导致你的AM长喝了一夜之后,你的老板。
升压的的shared_ptr
的例子就是信息。随着线程=单
,它甚至不能保证两个的shared_ptr
的情况下,从多个线程,是安全的独立操作。如果他们碰巧指向同一个对象(或从理论上说,在一些外来的实现,即使他们不这样做),你会创未定义行为,因为共享的状态将不会与适当的保护措施进行操作。
的在的线程=多
,这将不会发生。然而,它仍然是的不安全可以从多个线程访问同一个的shared_ptr
实例。也就是说,它不会给它不记录有问题的对象中的任何线程安全保障 - 但它确实给了预期/合理的/默认的独立对象是独立的保证。没有线程安全的这种默认级别一个好名字,但其实它是什么一般提供多线程语言的所有标准库今天。
作为最后一点,这是值得注意的是, Boost.Thread
被隐含总是与线程=多编译
- 因为使用Boost的多线程类是一个隐含的暗示,多线程是present。使用 Boost.Thread
无需多线程的支持将是荒谬的。
现在,所有的说,上面是背后编译助推与线程支持或不支持线程,它的宗旨是理论上的想法线程=
旗。在实践中,由于引入这个标志,多线程已经成为默认设置,并单线程例外。事实上,许多编译器和连接器缺省设为单线程的行为,现在默认为多线程 - 或至少是只需要一个提示(例如,在命令行上-pthread的presence)翻转到多线程
除此之外,同时也出现了协调一致的努力,使升压打造成为聪明 - 中,当环境有利于它应该翻转到多线程模式。这是pretty模糊,但未必如此。它得到弱联pthreads的符号复杂,因此,要使用MT或ST code实际上被推迟到运行时的决定 - 如果pthreads的可在执行时,这些符号将被使用,否则弱联存根 - 那什么也不做 - 将被使用。
的底线是,线程=多
是正确的,无害的,您的方案,特别是如果你正在制作一个二进制,你会分发到其他主机。如果没有特别的是,它的极有可能的,它无论如何都会正常工作,由于积累时间,甚至运行启发式,但你默默运行使用空存根方法的机会,或以其他方式使用MT不安全code。几乎没有缺点,使用正确的选择 - 但一些血淋淋的细节,也可以在评论这一点发现,和伊戈尔的答复以及
I am not entirely sure what exactly the threading=multi
flag does when building boost. The documentation says:
Causes the produced binaries to be thread-safe. This requires proper
support in the source code itself.
which does not seem to be very specific. Does this mean that the accesses to, for example, boost containers are guarded by mutexes/locks
or similar? As the performance of my code is critical, I would like to minimize any unnecessary mutexes etc.
Some more details:
My code is a plug-in DLL which gets loaded into a multi-threaded third-party application. I statically link boost into the DLL (the plug-in is not allowed to have any other dependencies except standard Windows DLLs, so I am forced to do this).
Although, the application is multi-threaded, most of the functions in my DLL are only ever called from a single thread and therefore the accesses to containers need not be guarded. I explicitly guard the the remaining places of my code, which can be called from multiple threads, by using boost::mutex
and friends.
I've tried building boost with both threading=multi
and threading=single
and both seem to work but I'd really like to know what I am doing here.
No, threading=multi
doesn't mean that things like boost containers will suddenly become safe for concurrent access by multiple threads (that would be prohibitively expensive from a performance point of view).
Rather, what it means in theory is that boost will be compiled to be thread aware. Basically this means that boost methods and classes will behave in a reasonable default way when accessed from multiple threads, much like classes in the std library. This means that you cannot access the same object from multiple threads, unless otherwise documented, but you can access different objects from multiple threads, safely. This might seem obvious, even without explicit support, but any static
state used by the library would break that guarantee if not protected. Using threading=multi
guarantees that any such shared state is property guarded by mutex or some other mechanism.
In the past similar arguments or stdlib flavors were available for the C and C++ std libraries supplied my compilers, although today mostly just the multithreaded versions are available.
There is likely little downside to compiling with threading=multi
, given that only a limited amount of static state need to be synchronized. Your comment that your library will mostly only be called by a single thread doesn't inspire a lot of confidence - after all, those are the kinds of latent bugs that will cause you to be woken up at 3 AM by your boss after a night of long drinking.
The example of boost's shared_ptr
is informative. With threading=single
, it is not even guaranteed that independent manipulation of two shared_ptr
instances, from multiple threads, is safe. If they happen to point to the same object (or, in theory, under some exotic implementations even if they don't), you will gen undefined behavior, because shared state won't be manipulated with the proper protections.
With threading=multi
, this won't happen. However, it is still not safe to access the same shared_ptr
instance from multiple threads. That is, it doesn't give any thread safety guarantees which aren't documented for the object in question - but it does give the "expected/reasonable/default" guarantees of independent objects being independent. There isn't a good name for this default level of thread-safety, but it is in fact what's generally offered all standard libraries for multi-threaded languages today.
As a final point, it's worth noting that Boost.Thread
is implicitly always compiled with threading=multi
- since using boost's multithreaded classes is an implicit hint that multiple threads are present. Using Boost.Thread
without multithreaded support would be nonsensical.
Now, all that said, the above is the theoretical idea behind compiling boost "with thread support" or "without thread support" which is the purpose of the threading=
flag. In practice, since this flag was introduced, multithreading has become the default, and single threading the exception. Indeed, many compilers and linkers which defaulted to single threaded behavior, now default to multithreaded - or at least require only a single "hint" (e.g., the presence of -pthread on the command line) to flip to multithreaded.
Apart from that, there has also been a concerted effort to make the boost build be "smart" - in that it should flip to multithreaded mode when the environment favors it. That's pretty vague, but necessarily so. It gets as complicated as weak-linking the pthreads symbols, so that the decision to use MT or ST code is actually deferred to runtime - if pthreads is available at execution time, those symbols will be used, otherwise weakly linked stubs - that do nothing at all - will be used.
The bottom line is that threading=multi
is correct, and harmless, for your scenario, and especially if you are producing a binary you'll distribute to other hosts. If you don't special that, it is highly likely that it will work anyway, due to the build-time and even runtime heuristics, but you do run the chance of silently using empty stub methods, or otherwise using MT-unsafe code. There is little downside to using the right option - but some of the gory details can also be found in the comments to this point, and Igor's reply as well.
这篇关于究竟`穿线= multi`编译的刺激时,做什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!