有没有一种可靠的方法可以强制线程在 C++ 中停止? (尤其是分离的)
Posted
技术标签:
【中文标题】有没有一种可靠的方法可以强制线程在 C++ 中停止? (尤其是分离的)【英文标题】:Is there a reliable way to force a thread to stop in C++? (especially detached ones) 【发布时间】:2016-05-17 16:11:37 【问题描述】:我最近正在使用 C++11 中的线程。现在我正在考虑如何强制停止线程。我在***上找不到,也试过这些。
每个线程一个变量:不太可靠 在主线程中返回:我必须强制退出一个而不是全部我没有更多的想法。我听说过 WinAPI,但我想要一个可移植的解决方案。 (这也意味着我不会使用 fork())
你能给我一个解决方案吗?我真的很想做。
【问题讨论】:
你的线程模型是什么?除非线程合作,否则 C++ 不提供任何强制关闭线程的方法。 没有。强制线程干净地停止是不可能的。有时有特定于平台的方法可以做到这一点,但它们总是不受欢迎,因为它们很危险。如果您在分配内存的过程中停止线程并破坏全局堆怎么办?如果你在它持有锁时停止它怎么办?等等。多线程需要精心设计。 至少我可以使用互斥锁,不是吗? 你将如何使用互斥锁?如果您解释了您的潜在问题,我们可能会提供更多帮助。 :-) 这不是一个真正的 C++ 问题。几乎可以肯定,您可以在平台 API 中对线程执行的任何操作都是 C 函数。 【参考方案1】:在 C++ 中强制关闭线程的最大问题之一是违反 RAII。
当一个函数(以及随后的一个线程)优雅地结束时,它所持有的一切都会被函数/线程创建的对象的析构函数优雅地清理掉。
内存被释放, 操作系统资源(句柄、文件描述符等)被关闭并返回给操作系统 锁正在解锁,因此其他线程可以使用它们保护的共享资源。 执行其他重要任务(例如更新计数器、记录等)。
如果你残忍地杀死一个线程(例如,在 Windows 上被 TerminateThread
杀死),这些都不会真正发生,并且程序处于非常危险的状态。
可以使用的(不是那么)常见的模式是注册一个“取消令牌”,如果其他线程要求,您可以在其上监视并优雅地关闭线程(a la TPL/PPL)。像
auto cancellationToken = std::make_shared<std::atomic_bool>();
cancellationToken->store(false);
class ThreadTerminator : public std::exception/*...*/;
std::thread thread([cancellationToken]
try
//... do things
if (cancellationToken->load())
//somone asked the thred to close
throw ThreadTerminator ();
//do other things...
if (cancellationToken->load())
//somone asked the thred to close
throw ThreadTerminator ();
//...
catch(ThreadTerminator)
return;
);
通常,一个小任务甚至不会打开一个新线程,最好将多线程应用程序视为并发任务和并行算法的集合。一个人为一些长期持续的后台任务打开一个新线程,这些任务通常在某种循环中执行(例如,接受传入的连接)。
因此,无论如何,要求取消小任务的情况无论如何都很少。
tldr:
在 C++ 中是否有可靠的方法强制线程停止?
没有。
【讨论】:
那么你的意思是每一种方法都不可靠?【参考方案2】:这是我大部分设计的方法:
想想两种线程:
1) 主要 - 我称之为 main。
2) 后续 - 由 main 或任何后续线程启动的任何线程
当我在 C++(或 C++ 中的 posix 线程)中启动 std::thread 时:
a) 我为所有后续线程提供对布尔“完成”的访问,初始化为 false。这个 bool 可以直接从 main 传递(或间接通过其他机制)。
b) 我所有的线程都有一个常规的“心跳”,通常使用 posix 信号量或 std::mutex,有时只使用一个计时器,有时只是在正常线程操作期间。
请注意,“心跳”不是轮询。
还要注意检查布尔值真的很便宜。
因此,每当 main 想要关闭时,它只是将 done 设置为 true 并“加入”后续线程。
有时 main 也会发出任何信号量(在加入之前)后续线程可能正在等待的信号。
有时,后续线程必须让其自己的后续线程知道该结束了。
这是一个例子 -
main 启动后续线程:
std::thread* thrd =
new std::thread(&MyClass_t::threadStart, this, id);
assert(nullptr != thrd);
请注意,我将 this 指针传递给此启动...在此类实例中是一个布尔 m_done。
主命令关机:
当然,在主线程中,我所做的只是
m_done = true;
在后续线程中(在此设计中,所有线程都使用相同的临界区):
void threadStart(uint id)
std::cout << id << " " << std::flush; // thread announce
do
doOnce(id); // the critical section is in this method
while(!m_done); // exit when done
最后,在外部范围内,main 调用连接。
也许要点是 - 在设计线程系统时,您还应该将系统设计为关闭,而不仅仅是添加它。
【讨论】:
以上是关于有没有一种可靠的方法可以强制线程在 C++ 中停止? (尤其是分离的)的主要内容,如果未能解决你的问题,请参考以下文章
Juc22_什么是中断interruptisInterruptedinterrupted方法源码解析如何使用中断标识停止线程