我想创建一个C ++类,其中一个线程每分钟做一次工作。
首先,我可以将线程定义为变量成员吗?
class my_class
{
public:
my_class()
: my_thread_(task, this)
{
}
~my_class()
{
done_ = true;
}
void run()
{
while(!done_)
{
...do work in the thread...
}
}
private:
static task(my_class * ptr)
{
ptr->run();
}
std::thread my_thread_;
std::atomic<bool> done_ = false;
};
其次,我可以使用带有线程的智能指针吗?
class my_class
{
public:
~my_class()
{
done_ = true;
}
void init()
{
my_thread_.reset(new std::thread(task, this));
}
void run()
{
while(!done_)
{
...do work in the thread...
}
}
private:
static task(my_class * ptr)
{
ptr->run();
}
std::unique_ptr<std::thread> my_thread_;
std::atomic<bool> done_ = false;
};
在我看来,我需要在它可以被销毁之前加入子线程,但我想知道std :: thread的析构函数是否知道这样做是安全的。
答案 0 :(得分:3)
可以创建std::unique_ptr<std::thread>
。当unique_ptr的范围结束时,它将调用std :: thread析构函数。请记住,调用std :: thread析构函数并不是通过std::terminate
轻轻地终止运行。要正常结束std :: thread,必须在std :: thread对象上运行.join()
。
答案 1 :(得分:3)
你可以把std::thread
放在任何你想要的地方,它们并不特别。销毁线程句柄是有问题的。您可以隐式分离,隐式删除或隐式连接,并且每个选项都很糟糕。 std::~thread
(通常)just kills the whole program。为了防止它join
或detach
由于您似乎想要隐式加入,您可能希望使用std::async
(可能使用std::launch::async
policy)来启动您的线程。它返回一个std::future
的析构函数隐式连接。
答案 2 :(得分:1)
线程对象没有关联的线程(并且安全 在
之后
- 是默认构造的
- 它已从
移出- join()被称为
- 分离()已被称为
因此,如果您将线程定义为成员变量并按如下方式编写析构函数:
~my_class()
{
done_ = true;
my_thread_.join();
}
一切都很好,因为标准保证std::thread
析构函数只能在my_class
析构函数see this Q/A之后调用。