假设我有一个工作线程tWorker
,它在构造Boss
时初始化,并告诉它work()
,直到bRetired
为真。 std::mutex
,mtx
会锁定一些数据(vFiles
),以便tWorker
在处理数据时拥有该数据。
tWorker
成为bRetired
后如何让true
“自杀”?当线程停止执行时,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;
}
}
备注
答案 0 :(得分:6)
一旦bRetired成为现实,我如何让tWorker“自杀”?
让控制流退出线程功能。 std::this_thread::yield()
调用不必要的内容。
当线程停止执行时,如何销毁互斥锁?
该互斥锁是Boss
类的成员。当对象被破坏时,它会在Boss
的析构函数中被破坏。
我读过std :: thread对象不能以任何方式中断。
C ++ API不提供终止任意线程的方法。必须有一种方法告诉线程终止,然后等到它确实如你所愿。
让线程什么都不做(或者调用std :: this_thread :: yield())提供与杀死线程相同的效果吗?
没有
虽然bRetired
变量存在竞争条件。它要么必须是std::atomic<bool>
,要么只有在锁定互斥锁时才能读取和修改。
答案 1 :(得分:5)
对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
超出范围时,它将被销毁,在这种情况下,当它的包含类被破坏时。