【发布时间】:2019-07-15 16:46:16
【问题描述】:
我正在使用 std::threads 来实现一个生产者,它会进行一些长时间的计算,但使用的代码没有提供中止方法。但是我需要调用线程在请求中止后立即继续。 所以我试图通过调用 detach() 来放弃线程。思路是线程完成计算,但结果被丢弃:
#include <thread>
#include <iostream>
#include <queue>
#include <mutex>
class C
{
public:
void spawn()
{
t1.swap(std::thread(&C::producer, this, 1));
}
void abort()
{
std::lock_guard<std::mutex> lk(mx);
aborted = true;
t1.detach();
}
bool tryGetResult(int &result)
{
std::lock_guard<std::mutex> lk(mx);
if (!q.empty()) {
result = q.front();
q.pop();
return true;
}
else
return false;
}
private:
std::thread t1;
std::mutex mx;
std::queue<int> q;
bool aborted = false;
void producer(int id)
{
int i = 0;
while (true) {
std::lock_guard<std::mutex> lk(mx);
if (aborted) break;
q.push(id * 10 + i);
i++;
}
}
};
int main()
{
{
C c;
c.spawn();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
c.abort();
}
std::cout << "Done...";
std::cin.get();
}
这种方法似乎有效,但对我来说它闻起来很臭。 我不明白为什么线程不会导致访问冲突,因为它会在对象被销毁后尝试访问它。
有没有办法通知线程它已经被分离并且必须退出而不访问任何类成员。
【问题讨论】:
-
为什么你认为它在对象被销毁后正在访问某些东西?
-
在对象被删除后访问对象是UB,可能的表现之一是程序看起来像预期的那样工作。
-
@NathanOliver 可以。
C在退出作用域后在主线程中被破坏,没有什么可以保证生产者会在此之前退出。 -
强行杀死(取消)线程是一个真的坏主意。线程都共享创建进程的相同地址空间,因此如果一个线程死了,您将不知道地址空间的状态是什么。要么通过
join()ing 等待线程终止,要么向它们发送一个信号,告诉它们它们应该通过一些atomic或mutex受保护的变量退出,它们已被写入定期检查。还阅读“条件变量”。简而言之:不要取消/杀死线程。请他们退出并写信让他们这样做。然后join他们知道他们已经这样做了。 -
这段代码闻起来像
std::future和std::promise或std::packaged_task的自己实现。
标签: c++ multithreading stdthread