如果我在std::thread
的构造函数中关闭Bar
何时停止运行?是否保证在Bar
实例被破坏时停止?
class Bar {
public:
Bar() : thread(&Bar:foo, this) {
}
...
void foo() {
while (true) {//do stuff//}
}
private:
std::thread thread;
};
编辑:如何在析构函数中正确终止std::thread
?
答案 0 :(得分:2)
如果我在Bar的构造函数中关闭std :: thread的话 停止运行?
只要执行你提供的callable,程序就会终止运行。
当Bar实例被破坏时,它是否可以保证停止?
没有。为了保证这一点,请在std::thread::join
析构函数中调用Bar
。
实际上,如果您在thread::join
之前没有致电thread::detach
或Bar::~Bar
,则会自动致电std::terminate
来终止您的申请。所以必须调用join
(首选)或detach
(不太推荐)。
你还想在对象析构函数上调用therad::join
因为生成的线程依赖于对象是活着的,如果在你的线程处理该对象时对象被破坏 - 您正在使用被破坏的对象,并且您的代码中将存在未定义的行为。
答案 1 :(得分:0)
简短回答:是和否。是的,线程结束,但不是通常的方式(杀死线程),而是由于<div id="wrapper-for-demo"><!-- just to fit nicely in the stacksnippets results window -->
<!-- an image with a square source -->
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" style="background-image:url(http://placehold.it/400x400)" />
<!-- an image with a non-square source -->
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" style="background-image:url(http://placehold.it/400x600)" />
</div>
调用而退出的主线程。
答案很长:当底层函数( thread )完成执行时,只能安全地破坏线程。这可以通过两种方式完成
std::terminate
,等待线程完成(在您的情况下,永远不会)join()
,它将线程与主线程分离(在这种情况下,线程将在主线程关闭时结束 - 当程序终止时)。如果所有those conditions都不适用,则调用析构函数,然后调用detach()
:
它是默认构造的
- 移出
它已从
std::terminate
被称为
join()
被称为
答案 2 :(得分:0)
C ++线程工具不包含用于终止线程的内置机制。相反,你必须自己决定:a)一个机制来通知线程它应该终止,b)你不关心线程在进程终止时中止操作并且操作系统只是停止运行它#39 ; s线程了。
std::thread
对象不是线程本身,而是包含线程描述符/句柄的不透明对象,因此理论上它可以在不影响线程的情况下被销毁,并且有支持和反对自动终止的参数线程本身。相反,作为妥协,它是这样做的,以便在线程保持运行和附加时销毁std::thread
对象将导致应用程序终止。
结果,在它的析构函数中有一些代码如下:
~thread() {
if (this->joinable())
std::terminate(...);
}
这是一个使用简单原子变量并在线程中检查它的示例。对于更复杂的情况,您可能需要考虑condition_variable
或其他更复杂的信令机制。
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
class S {
std::atomic<bool> running_;
std::thread thread_;
public:
S() : running_(true), thread_([this] () { work(); }) {}
void cancel() { running_ = false; }
~S() {
if ( running_ )
cancel();
if ( thread_.joinable() )
thread_.join();
}
private:
void work() {
while ( running_ ) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "tick ...\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "... tock\n";
}
std::cout << "!running\n";
}
};
int main()
{
std::cout << "main()\n";
{
S s;
std::this_thread::sleep_for(std::chrono::milliseconds(2750));
std::cout << "end of main, should see a tock and then end\n";
}
std::cout << "finished\n";
}