C++ 告诉 std::thread 在满足条件时杀死/停止自己
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18868114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Telling an std::thread to kill/stop itself when a condition is met
提问by alxcyl
Say I have a worker thread tWorker
, which is initialized when Boss
is constructed and tells it to do work()
, until bRetired
is true. An std::mutex
, mtx
, locks some data (vFiles
) so that tWorker
owns it when he's working on it.
假设我有一个工作线程tWorker
,它在Boss
构造时初始化并告诉它执行work()
,直到bRetired
为真。一std::mutex
,mtx
,锁定一些数据(vFiles
),使tWorker
拥有它的时候,他的工作就可以了。
How do I make tWorker
"commit suicide" once bRetired
becomes true
? How would the mutex
be destroyed when the thread stops execution?
我如何让tWorker
“自杀”一旦bRetired
变成true
?mutex
线程停止执行时如何销毁?
I've read that std::thread
objects cannot be interrupted in any way. Does letting the thread do nothing (or calling std::this_thread::yield()
) provide the same effect as killing the thread?
我读过std::thread
不能以任何方式中断对象。让线程什么都不做(或调用std::this_thread::yield()
)与杀死线程的效果相同吗?
class Boss {
private:
std::thread tWorker;
std::mutex mtx;
bool bRetired;
std::vector< std::string > vFiles;
void work() {
while ( bRetired == false ) {
// Do your job!
mtx.lock();
// ... Do something about vFiles ...
mtx.unlock();
}
// tWorker has retired, commit suicide
// ** How? **
// Does this suffice if I want to "kill" the thread?
std::this_thread::yield();
}
public:
Boss() {
bRetired = false;
tWorker = std::thread( &Boss::work, this );
// Have worker do its job independently
// **Bonus Question** : Should this be tWorker.join() or tWorker.detach()?
tWorker.detach();
}
retire() {
bRetired = true;
}
}
Notes
笔记
- The worker thread cannot be started again once it is retired.
- The worker thread works on the background without interrupting the main thread's execution.
- 工作线程一旦退役就无法再次启动。
- 工作线程在后台工作,不会中断主线程的执行。
采纳答案by hmjd
The call to std::thread::yield()
is unrequired and does not kill the calling thread:
std::thread::yield()
不需要调用并且不会终止调用线程:
Provides a hint to the implementation to reschedule the execution of threads, allowing other threads to run.
向实现提供提示以重新安排线程的执行,从而允许其他线程运行。
Just exit the function to exit the thread.
只需退出函数即可退出线程。
Note that the use of bRetired
is incorrect as two threads can be accessing the same memory location and one of those threads is modifying it: this is undefined behaviour. Also, the change made in the function retire()
, a different thread, will not be seen by the thread executing run()
: use atomic<bool>
for atomicity and visibility.
请注意,使用bRetired
是不正确的,因为两个线程可以访问相同的内存位置,而其中一个线程正在修改它:这是未定义的行为。此外,在函数中所做的更改retire()
,一个不同的线程,不会被执行的线程看到run()
:atomic<bool>
用于原子性和可见性。
If join()
was used within the constructor the constructor would not return until the thread exited, which would never happen as it would be impossible to call retire()
because the object would not be available (as the constructor would not have returned). If it is required to synchronize with the exiting of the thread then do not detach()
but join()
in the retire()
function:
如果join()
在构造函数中使用,则构造函数在线程退出之前不会返回,这永远不会发生,retire()
因为无法调用,因为对象不可用(因为构造函数不会返回)。如果需要与线程的退出同步,则不要detach()
只join()
在retire()
函数中:
void retire() {
bRetired = true;
tWorker.join();
}
Use RAII for acquiring mutex
es (std::lock_guard
for example) to ensure it always released. The mutex
will be destroyed when it goes out of scope, in this case when its containing class is destructed.
使用 RAII 获取mutex
es(std::lock_guard
例如)以确保它始终被释放。在mutex
当它超出范围,在这种情况下,当其包含的类被破坏就会被破坏。
回答by Maxim Egorushkin
How do I make tWorker "commit suicide" once bRetired becomes true?
一旦 bRetired 变为真,我如何让 tWorker “自杀”?
You let the control flow exit the thread function. That std::this_thread::yield()
call in unnecessary.
你让控制流退出线程函数。那个std::this_thread::yield()
电话是不必要的。
How would the mutex be destroyed when the thread stops execution?
当线程停止执行时,互斥量将如何销毁?
That mutex is a member of Boss
class. It gets destroyed in the destructor of Boss
when the object is getting destroyed.
该互斥体是Boss
类的成员。它Boss
在对象被销毁时的析构函数中被销毁。
I've read that std::thread objects cannot be interrupted in any way.
我读过 std::thread 对象不能以任何方式中断。
C++ API does not provide means to terminate an arbitrary thread. There has to be a way to tell a thread to terminate and then wait till it does, as you intend to do.
C++ API 不提供终止任意线程的方法。必须有一种方法告诉线程终止,然后按照您的意图等待它终止。
Does letting the thread do nothing (or calling std::this_thread::yield()) provide the same effect as killing the thread?
让线程什么都不做(或调用 std::this_thread::yield() )是否提供与杀死线程相同的效果?
No.
不。
There is a race condition on bRetired
variable though. It either needs to be std::atomic<bool>
or it should only be read and modified only when that mutex is locked.
bRetired
但是,变量存在竞争条件。它要么需要,要么std::atomic<bool>
只有在该互斥锁被锁定时才能读取和修改。