告诉 std::thread 在满足条件时杀死/停止自身
Telling an std::thread to kill/stop itself when a condition is met
>假设我有一个工作线程tWorker
,它在构造Boss
时初始化并告诉它执行work()
,直到bRetired
为真。mtx
,一个std::mutex
锁定了一些数据(vFiles
),以便tWorker
在处理数据时拥有它。
一旦bRetired
变得true
,如何让tWorker
"自杀"?当线程停止执行时,如何销毁mutex
?
我读过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;
}
}
笔记
- 工作线程一旦停用,就无法再次启动。 工作线程
- 在后台工作,而不会中断主线程的执行。
一旦b退休成为真的,我如何让tWorkers"自杀"?
让控制流退出线程函数。这std::this_thread::yield()
不必要的
当线程停止执行时,互斥锁将如何销毁?
该互斥锁是Boss
类的成员。当对象被销毁时,它会在Boss
的析构函数中被销毁。
我读过 std::thread 对象不能以任何方式中断。
C++ API 不提供终止任意线程的方法。必须有一种方法可以告诉线程终止,然后等到它终止,就像你打算做的那样。
让线程不做任何事情(或调用 std::this_thread::yield())是否提供与杀死线程相同的效果?
不。
不过,bRetired
变量上存在竞争条件。它要么需要std::atomic<bool>
,要么只应在锁定该互斥锁时才读取和修改。
对 std::thread::yield()
的调用是不需要的,并且不会终止调用线程:
向实现提供提示,以重新计划线程的执行,从而允许其他线程运行。
只需退出函数即可退出线程。
请注意,使用 bRetired
是不正确的,因为两个线程可以访问相同的内存位置,其中一个线程正在修改它:这是未定义的行为。此外,在函数retire()
(一个不同的线程)中所做的更改不会被执行run()
的线程看到:使用 atomic<bool>
来实现原子性和可见性。
如果在构造函数中使用join()
则构造函数在线程退出之前不会返回,这永远不会发生,因为无法调用retire()
因为对象不可用(因为构造函数不会返回)。如果需要与线程的退出同步,则不要detach()
,而是join()
retire()
函数:
void retire() {
bRetired = true;
tWorker.join();
}
使用 RAII 获取mutex
es(例如std::lock_guard
)以确保它始终释放。mutex
在超出范围时将被销毁,在这种情况下,当其包含类被销毁时。
- 在std::thread中,joinable()然后join()线程安全吗
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 分离一个静态常量 std::thread?
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 如何从 std::thread 返回值
- 将 std::thread by 值推送到列表中
- 转发变量参数列表以模拟 std::thread
- 嵌入式设备 -> std::thread -> FreeRTOS?
- 对 'std::thread::_M_start_thread CMake 的未定义引用进行基准测试
- std::thread 增加 DLL 引用计数,从而防止卸载 DLL
- 如何防止 std::thread 在 QT 中冻结 GUI?
- 对带有唯一指针的 std::thread 使用类成员函数时出现编译错误
- 为什么参数在构造 std::thread 时移动两次
- std::thread::_Invoker 使用线程编程时出错
- 在线程 A 中创建一个 std::thread 对象,在线程 B 中连接
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?
- 将模板(没有规范)传递给 std::thread() 会出现错误:<未解析的重载函数类型>匹配错误
- 使用 std::thread & std::bind 在成员函数中启动线程
- 从gcc 5.4升级至gcc 6.3 std::thread std:ref issue