用 c++11 等价物替换 boost::thread 和 boost::mutex 是否明智?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7241993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it smart to replace boost::thread and boost::mutex with c++11 equivalents?
提问by NoSenseEtAl
Motivation: reason why I'm considering it is that my genius project manager thinks that boost is another dependency and that it is horrible because "you depend on it"(I tried explaining the quality of boost, then gave up after some time :( ). Smaller reason why I would like to do it is that I would like to learn c++11 features, because people will start writing code in it. So:
动机:我考虑它的原因是我的天才项目经理认为 boost 是另一种依赖,而且它很可怕,因为“你依赖它”(我尝试解释 boost 的质量,然后在一段时间后放弃了:( ) 更小的原因是我想学习c++11的特性,因为人们会开始在里面写代码。所以:
- Is there a 1:1 mapping between
#include<thread> #include<mutex>
and boost equivalents? - Would you consider a good idea to replace boost stuff with c++11
stuff. My usage is primitive, but are there examples when std doesnt offer what boost does? Or (blasphemy) vice versa?
#include<thread> #include<mutex>
和 boost 等效项之间是否存在 1:1 映射?- 你认为用c++11的
东西替换boost的东西是个好主意吗?我的用法很原始,但是有没有 std 不提供 boost 功能的例子?或者(亵渎)反之亦然?
P.S. I use GCC so headers are there.
PS我使用GCC所以标题在那里。
回答by Anthony Williams
There are several differences between Boost.Thread and the C++11 standard thread library:
Boost.Thread 和 C++11 标准线程库有几个区别:
- Boost supports thread cancellation, C++11 threads do not
- C++11 supports
std::async
, but Boost does not - Boost has a
boost::shared_mutex
for multiple-reader/single-writer locking. The analogousstd::shared_timed_mutex
is available only since C++14 (N3891), whilestd::shared_mutex
is available only since C++17 (N4508). - C++11 timeouts are different to Boost timeouts (though this should soon change now Boost.Chrono has been accepted).
- Some of the names are different (e.g.
boost::unique_future
vsstd::future
) - The argument-passing semantics of
std::thread
are different toboost::thread
--- Boost usesboost::bind
, which requires copyable arguments.std::thread
allows move-only types such asstd::unique_ptr
to be passed as arguments. Due to the use ofboost::bind
, the semantics of placeholders such as_1
in nested bind expressions can be different too. - If you don't explicitly call
join()
ordetach()
then theboost::thread
destructor and assignment operator will calldetach()
on the thread object being destroyed/assigned to. With a C++11std::thread
object, this will result in a call tostd::terminate()
and abort the application.
- Boost 支持线程取消,C++11 线程不支持
- C++11 支持
std::async
,但 Boost 不支持 - Boost 有一个
boost::shared_mutex
多读/单写锁定。类似std::shared_timed_mutex
的仅自 C++14 ( N3891)std::shared_mutex
起可用,而仅自 C++17 ( N4508)起可用。 - C++11 超时与 Boost 超时不同(尽管现在 Boost.Chrono 已被接受,这应该很快就会改变)。
- 有些名称不同(例如
boost::unique_future
vsstd::future
) - 的参数传递语义
std::thread
与boost::thread
--- Boost uses不同boost::bind
,后者需要可复制的参数。std::thread
允许仅移动类型,例如std::unique_ptr
作为参数传递。由于使用boost::bind
,占位符的语义(例如_1
在嵌套绑定表达式中)也可能不同。 - 如果您没有显式调用
join()
ordetach()
则boost::thread
析构函数和赋值运算符将调用detach()
被销毁/分配给的线程对象。对于 C++11std::thread
对象,这将导致调用std::terminate()
并中止应用程序。
To clarify the point about move-only parameters, the following is valid C++11, and transfers the ownership of the int
from the temporary std::unique_ptr
to the parameter of f1
when the new thread is started. However, if you use boost::thread
then it won't work, as it uses boost::bind
internally, and std::unique_ptr
cannot be copied. There is also a bug in the C++11 thread library provided with GCC that prevents this working, as it uses std::bind
in the implementation there too.
为了澄清关于仅移动参数的观点,以下是有效的 C++11,并将 的所有权int
从临时std::unique_ptr
转移到f1
新线程启动时的参数。但是,如果您使用boost::thread
它,它将无法工作,因为它在boost::bind
内部使用,并且std::unique_ptr
无法复制。GCC 提供的 C++11 线程库中还有一个错误,它阻止了这项工作,因为它std::bind
也在那里的实现中使用。
void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));
If you are using Boost then you can probably switch to C++11 threads relatively painlessly if your compiler supports it (e.g. recent versions of GCC on linux have a mostly-complete implementation of the C++11 thread library available in -std=c++0x
mode).
如果您正在使用 Boost,那么如果您的编译器支持它,您可能可以相对轻松地切换到 C++11 线程(例如,Linux 上的最新版本的 GCC 具有在-std=c++0x
模式下可用的 C++11 线程库的大部分完整实现)。
If your compiler doesn't support C++11 threads then you may be able to get a third-party implementation such as Just::Thread, but this is still a dependency.
如果您的编译器不支持 C++11 线程,那么您可能可以获得第三方实现,例如Just::Thread,但这仍然是一个依赖项。
回答by Alex B
std::thread
is largely modelled after boost::thread
, with a few differences:
std::thread
主要仿照boost::thread
,但有一些不同:
- boost's non-copyable, one-handle-maps-to-one-os-thread, semantics are retained. But this thread is movable to allow returning thread from factory functions and placing into containers.
- This proposal adds cancellation to the
boost::thread
, which is a significant complication. This change has a large impact not only on thread but the rest of the C++ threading library as well. It is believed this large change is justifiable because of the benefit.
- The thread destructor must now call cancel prior to detaching to avoid accidently leaking child threads when parent threads are canceled.
- An explicit detach member is now required to enable detaching without canceling.
- The concepts of thread handle and thread identity have been separated into two classes (they are the same class in
boost::thread
). This is to support easier manipulation and storage of thread identity.- The ability to create a thread id which is guaranteed to compare equal to no other joinable thread has been added (
boost::thread
does not have this). This is handy for code which wants to know if it is being executed by the same thread as a previous call (recursive mutexes are a concrete example).- There exists a "back door" to get the native thread handle so that clients can manipulate threads using the underlying OS if desired.
- boost 的不可复制的、一个句柄映射到一个操作系统线程的语义被保留。但是这个线程是可移动的,以允许从工厂函数返回线程并放入容器中。
- 这个提议增加了对 的取消
boost::thread
,这是一个重大的并发症。这种变化不仅对线程有很大影响,对 C++ 线程库的其余部分也有很大影响。相信这种巨大的变化是合理的,因为它带来了好处。
- 线程析构函数现在必须在分离之前调用取消以避免在取消父线程时意外泄漏子线程。
- 现在需要一个明确的分离成员来启用分离而不取消。
- 线程句柄和线程标识的概念被分成了两个类(它们是 中的同一个类
boost::thread
)。这是为了支持更轻松地操作和存储线程标识。- 添加了创建线程 id 的能力,该线程 id 保证与没有其他可连接线程的比较相等(
boost::thread
没有这个)。这对于想要知道它是否由与先前调用相同的线程执行的代码很方便(递归互斥是一个具体示例)。- 存在一个“后门”来获取本机线程句柄,以便客户端可以在需要时使用底层操作系统操作线程。
This is from 2007, so some points are no longer valid: boost::thread
has a native_handle
function now, and, as commenters point out, std::thread
doesn't have cancellation anymore.
这是从 2007 年开始的,所以有些点不再有效:现在boost::thread
有一个native_handle
功能,并且正如评论者指出的那样,std::thread
不再有取消。
I could not find any significant differences between boost::mutex
and std::mutex
.
我找不到boost::mutex
和之间的任何显着差异std::mutex
。
回答by ks1322
There is one reason not to migrate to std::thread
.
不迁移到std::thread
.
If you are using static linking, std::thread
becomes unusable due to these gcc bugs/features:
如果您使用静态链接,std::thread
由于这些 gcc 错误/功能而变得无法使用:
Namely, if you call std::thread::detach
or std::thread::join
it will lead to either exception or crash, while boost::thread
works ok in these cases.
也就是说,如果你调用std::thread::detach
或者std::thread::join
它会导致异常或崩溃,而boost::thread
在这些情况下工作正常。
回答by Nicholas Smith
Enterprise Case
企业案例
If you are writing software for the enterprise that needs to run on a moderate to large variety of operating systems and consequently build with a variety of compilers and compiler versions (especially relatively old ones) on those operating systems, my suggestion is to stay away from C++11 altogether for now. That means that you cannot use std::thread
, and I would recommend using boost::thread
.
如果您正在为需要在中等到多种操作系统上运行并因此在这些操作系统上使用各种编译器和编译器版本(尤其是相对较旧的版本)构建的企业编写软件,我的建议是远离现在一共是 C++11。这意味着您不能使用std::thread
,我建议使用boost::thread
.
Basic / Tech Startup Case
基本/技术启动案例
If you are writing for one or two operating systems, you know for sure that you will only ever need to build with a modern compiler that mostly supports C++11 (e.g. VS2015, GCC 5.3, Xcode 7), and you are not already dependent on the boost library, then std::thread
could be a good option.
如果您正在为一两个操作系统编写代码,您肯定知道您只需要使用主要支持 C++11(例如 VS2015、GCC 5.3、Xcode 7)的现代编译器进行构建,而您还没有依赖于 boost 库,那么std::thread
可能是一个不错的选择。
My Experience
我的经验
I am personally partial to hardened, heavily used, highly compatible, highly consistent libraries such as boost versus a very modern alternative. This is especially true for complicated programming subjects such as threading. Also, I have long experienced great success with boost::thread
(and boost in general) across a vast array of environments, compilers, threading models, etc. When its my choice, I choose boost.
我个人偏爱强化的、大量使用的、高度兼容的、高度一致的库,例如 boost 与非常现代的替代方案。对于线程等复杂的编程主题尤其如此。此外,长期以来,我boost::thread
在各种环境、编译器、线程模型等方面都取得了巨大的成功(以及一般的 boost)。当我选择时,我选择了 boost。
回答by Robert Hegner
With Visual Studio 2013 the std::mutex
seems to behave differently than the boost::mutex
, which caused me some problems (see this question).
在 Visual Studio 2013 中,它的std::mutex
行为似乎与 不同boost::mutex
,这给我带来了一些问题(请参阅此问题)。
回答by Robert Fraser
With regards to std::shared_mutex added in C++17
关于 C++17 中添加的 std::shared_mutex
The other answers here provide a very good overview of the differences in general. However, there are several issues with std::shared_mutex
that boost solves.
此处的其他答案很好地概述了总体差异。但是,std::shared_mutex
该提升解决了几个问题。
Upgradable mutices. These are absent from
std::thread
. They allow a reader to be upgraded to a writer without allowing any other writers to get in before you. These allow you to do things like pre-process a large computation (for example, reindexing a data structure) when in read mode, then upgrade to write to apply the reindex while only holding the write lock for a short time.Fairness. If you have constant read activity with a
std::shared_mutex
, your writers will be softlocked indefinitely. This is because if another reader comes along, they will always be given priority. Withboost:shared_mutex
, all threads will eventuallybe given priority.(1)Neither readers nor writers will be starved.
可升级的静音。这些在
std::thread
. 它们允许读者升级为作者,而不允许任何其他作者先于您进入。这些允许您在读取模式下执行诸如预处理大型计算(例如,重新索引数据结构)之类的操作,然后升级到写入以应用重新索引,同时仅在短时间内持有写锁。公平。如果你有持续的读取活动
std::shared_mutex
,你的作者将被无限期地软锁定。这是因为如果有其他读者出现,他们将始终获得优先权。使用boost:shared_mutex
,所有线程最终都会获得优先权。(1)读者和作者都不会饿死。
The tl;dr of this is that if you have a very high-throughput system with no downtime and very high contention, std::shared_mutex
will never work for you without manually building a priority system on top of it. boost::shared_mutex
will work out of the box, although you might need to tinker with it in certain cases. I'd argue that std::shared_mutex
's behavior is a latent bug waiting to happen in most code that uses it.
总而言之,如果您有一个吞吐量非常高的系统,没有停机时间和非常高的争用,std::shared_mutex
那么如果不在其上手动构建优先级系统,它将永远不会为您工作。boost::shared_mutex
将开箱即用,尽管在某些情况下您可能需要修改它。我认为std::shared_mutex
的行为是在大多数使用它的代码中等待发生的潜在错误。
(1)The actual algorithm it usesis based on the OS thread scheduler. In my experience, when reads are saturated, there are longer pauses (when obtaining a write lock) on Windows than on OSX/Linux.
(1)它使用的实际算法是基于 OS 线程调度程序的。根据我的经验,当读取饱和时,Windows 上的停顿时间(获得写锁时)比 OSX/Linux 上的要长。
回答by user3323559
I tried to use shared_ptr from std instead of boost and I actually found a bug in gcc implementation of this class. My application was crashing because of destructor called twice (this class should be thread-safe and shouldn't generate such problems). After moving to boost::shared_ptr all problems disappeared. Current implementations of C++11 are still not mature.
我尝试使用 std 中的 shared_ptr 而不是 boost ,实际上我在这个类的 gcc 实现中发现了一个错误。我的应用程序因为两次调用析构函数而崩溃(这个类应该是线程安全的,不应该产生这样的问题)。移动到 boost::shared_ptr 后,所有问题都消失了。C++11 的当前实现仍然不成熟。
Boost has also more features. For example header in std version doesn't provide serializer to a stream (i.e. cout << duration). Boost has many libraries that use its own , etc. equivalents, but do not cooperate with std versions.
Boost还有更多的功能。例如,std 版本中的标头不提供流的序列化程序(即 cout << 持续时间)。Boost 有许多库使用它自己的等价物,但不与 std 版本合作。
To sum up - if you already have an application written using boost, it is safer to keep your code as it is instead of putting some effort in moving to C++11 standard.
总而言之 - 如果您已经有一个使用 boost 编写的应用程序,那么保持代码原样比努力转向 C++11 标准更安全。