std::thread
不能简单地被类继承,不能在销毁时自动加入等等。
很多陷阱,比如需要使用 std::atomic_bool
来停止,在使用 std::thread
时不能简单地共享对象的 this
作为成员变量来执行成员方法。
使用 std::thread
实现类 QThread 有什么好的做法吗?
我的目标是一个可继承的 Thread 类,启用 start()
、detach()
、stop()
功能。
例如我写了一个如下:
#include <atomic>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <thread>
#include <vector>
struct Thread {
Thread(int id) {
std::atomic_init(&(this->id), id);
std::atomic_init(&(this->m_stop), false);
}
Thread(Thread &&rhs) :
id(),
m_stop(),
m_thread(std::move(rhs.m_thread))
{
std::atomic_init(&(this->id), rhs.id.load());
rhs.id.store(-1);
std::atomic_init(&(this->m_stop), rhs.m_stop.load());
}
virtual ~Thread() {
this->stop();
}
void start() {
this->m_thread = std::move(std::thread(&Thread::work, this));
}
void stop() {
this->m_stop.store(true);
if (this->m_thread.joinable()) {
this->m_thread.join();
}
}
virtual void work() {
while (!(this->m_stop)) {
std::chrono::milliseconds ts(5000);
std::this_thread::sleep_for(ts);
}
}
std::atomic_int id;
std::atomic_bool m_stop;
std::thread m_thread;
};
int main() {
srand(42);
while (true) {
std::vector<Thread> v;
for (int i = 0; i < 10; ++i) {
auto t = Thread(i);
v.push_back(std::move(t));
printf("Start %d\n", i);
v[i].start();
}
printf("Start fin!\n");
int time_sleep = rand() % 2000 + 1000;
std::chrono::milliseconds ts(time_sleep);
std::this_thread::sleep_for(ts);
for (int i = 0; i < 10; ++i) {
printf("Stop %d\n", i);
v[i].stop();
printf("Pop %d\n", i);
v.pop_back();
}
printf("Stop fin!\n");
}
return 0;
}
但我很难把它弄好,就在 Stop 0
之后它陷入僵局,或者有时它发生核心转储。
最佳答案
std::thread
旨在作为实现线程原语的最低构建 block 。因此,它不像 QThread 那样提供丰富的接口(interface),但与标准库中的同步原语一起,它允许您非常轻松地实现更复杂的行为,如 QThread 提供的行为。
你正确地注意到从 std::thread
继承是一个坏主意(没有虚拟析构函数是一个死的赠品)而且我认为拥有多态 Thread 类型并不是最聪明的设计放在首位,但如果需要,您可以轻松地将 std::thread
封装为任何类(多态或非多态)的成员。
加入破坏实际上只是一种政策。将 std::thread
封装为成员的类可以简单地在其析构函数中调用 join
,有效地实现销毁时的自连接。并发在这里无关紧要,因为根据定义,对象销毁总是非并发执行的。如果您想在多个(可能同时调用的)执行路径之间共享一个线程的所有权,std::shared_ptr
将为您处理。但即使在这里,析构函数也总是由最后一个放弃其 shared_ptr
的剩余线程非并发执行。
QThread::isInterruptionRequested
之类的东西可以用单个标志实现,访问它当然必须由类同步(使用互斥锁或使用原子标志)。
标准未指定更改线程的优先级,因为并非标准设想的所有平台都允许这样做,但您可以使用 native_handle
使用特定于平台的代码自行实现。
等等。所有零件都在那里,您只需根据需要组装它们即可。
关于c++ - 如何使用 c++11 std::thread 实现类 QThread 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42670837/