今天主管找我了一个方案设计提到一个他们用Java做的一个状态机,他的做法是,当基于状态设计模式的状态机的实际状态发生变化时,执行相应的动作(也就是调用对应的函数),他的做法是将一个继承了Runnable的对象提交到一个线程池里面,听到这都没问题,问题在于他说可以从外部中止当前执行的任务,他的意思是调用他Java的Thread类的interrupt函数来打断当前线程中函数的执行。我当时有点迷惑,因为C++标准库里并没有提供这样的 *** 作,甚至在C++20 引入的基于std::thread的封装的jthread也不能做到这一点,标准库之所以这样做是因为这样做,十有八九会导致内存泄漏,文件描述符泄露,甚至造成死锁的风险。那么标注库不支持, *** 作系统有能不能做到呢?答案是可以的。下面以基于POSIX的pthread库为例:
auto fun = [] {
for (;;) {
std::this_thread::sleep_for(300ms);
std::cout << "thread:" << std::this_thread::get_id() << "\n";
}
};
auto main() -> int {
auto th = std::thread(fun);
std::this_thread::sleep_for(2s);
::pthread_cancel(th.native_handle());
th.join();
return {};
}
输出为:
thread:140679200679488
thread:140679200679488
thread:140679200679488
thread:140679200679488
thread:140679200679488
thread:140679200679488
可以看到纸打印了6次(有限次)就退出了。th.native_handle()
返还出系统软件线程句柄
struct Main {
Main() { std::cout << "ctor\n"; }
~Main() { std::cout << "dtor\n"; }
};
auto fun = [] {
auto ptr = new Main();
for (;;) {
std::this_thread::sleep_for(300ms);
std::cout << "thread:" << std::this_thread::get_id() << "\n";
}
};
auto main() -> int {
auto th = std::thread(fun);
std::this_thread::sleep_for(2s);
::pthread_cancel(th.native_handle());
th.join();
return {};
}
ctor
thread:140618021824064
thread:140618021824064
thread:140618021824064
thread:140618021824064
thread:140618021824064
thread:140618021824064
可以看到这里虽然指针变量出栈,但是其引用的Main对象泄露了
很简单做法改为智能指针
auto fun = [] {
auto ptr = std::make_shared<Main>();
for (;;) {
std::this_thread::sleep_for(300ms);
std::cout << "thread:" << std::this_thread::get_id() << "\n";
}
};
ctor
thread:140608551016000
thread:140608551016000
thread:140608551016000
thread:140608551016000
thread:140608551016000
thread:140608551016000
dtor
不过这里创建在堆上的对象相较于栈上对象没有一点优势,创建和释放都没栈上对象来得方便。所以我感觉一个注定被中止的线程,内部执行的函数一定要十分注意,一定要遵循RAII,这一点包括fd的管理,要用基于RAII的对象管理。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)