为啥我会在这个程序中“中止”? [复制]
Posted
技术标签:
【中文标题】为啥我会在这个程序中“中止”? [复制]【英文标题】:Why do I get "abort" on this program? [duplicate]为什么我会在这个程序中“中止”? [复制] 【发布时间】:2017-02-07 16:24:18 【问题描述】:让我们谈谈下一个代码示例:
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <deque>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
std::deque<int> queue;
void Inserter()
int count = 10;
while (count >= 0)
std::unique_lock<std::mutex> lock(mtx);
queue.push_back(count);
--count;
lock.unlock();
void Consumer()
int count = 10, got;
while (count >= 0)
std::unique_lock<std::mutex> lock(mtx);
if (!queue.empty())
got = queue.back();
queue.pop_back();
std::cout << "We got: " << got << std::endl;
--count;
lock.unlock();
else
lock.unlock();
int main()
std::thread t1(Inserter);
std::thread t2(Consumer);
std::cin.get();
return 0;
当我运行这个程序时,我得到“中止”,但我不应该这样做。 我在这里看到中止的唯一原因是当我离开锁定的锁而没有打开它时 - 但是没有任何理由让锁保持锁定,因为在每个循环之后我都会打开锁。
你看到的原因是什么?
【问题讨论】:
您是否尝试使用调试器单步执行您的代码? 获得“中止”并不是具体的描述。您是否在标准库中触发断言,是否导致访问冲突,...? 如果这是 Visual Studio,请在对话框出现时按 Debug,然后将调用堆栈向上移动到您的代码。 【参考方案1】:您不会在主程序中调用std::thread::join
。当t2
超出范围时,你调用它的析构函数,由于你还没有加入线程,它会导致中止。
顺便说一句,您无需致电lock.unlock()
。 std::unique_lock
的全部意义在于它会在对象被破坏时自动执行此操作。 (在您从队列中获取值的地方声明 got
会更简洁。)
所以你的代码应该是这样的:
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <deque>
std::mutex mtx;
std::deque<int> queue;
void Inserter()
for (int count = 10; count >= 0; --count)
std::unique_lock<std::mutex> lock(mtx);
queue.push_back(count);
void Consumer()
for (int count = 10; count >= 0; )
std::unique_lock<std::mutex> lock(mtx);
if (!queue.empty())
const int got = queue.back();
queue.pop_back();
std::cout << "We got: " << got << std::endl;
--count;
int main()
std::thread t1(Inserter);
std::thread t2(Consumer);
t1.join();
t2.join();
std::cin.get();
return 0;
调用join
的要求是因为一个常见的习惯用法是使Inserter
成为从std::thread
派生的类,并让Inserter
构造函数将合适的线程函数传递给std::thread
构造函数。如果类包含线程方法访问的成员变量,那么如果在对象被破坏后线程方法继续运行,那就不好了。该标准要求您通过调用join
(在这种情况下线程方法已完成)或调用detach
(在这种情况下,您有责任确保不访问已经消失的变量)来避免这种情况超出范围)。
【讨论】:
你说得对。现在可以了。但它有什么理由自毁呢? t2 线程在 main 完成之前完成了他的工作(我有 cin 可以阻止 main 超出范围) 我的段落解释了吗?【参考方案2】:要解决您需要在两个线程上调用std::thread::join
的问题
int main()
std::thread t1(Inserter);
std::thread t2(Consumer);
t1.join();
t2.join();
return 0;
演示:here
【讨论】:
以上是关于为啥我会在这个程序中“中止”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥从函数返回数组作为参数时,我会从函数中的数组中获取随机值? [复制]
为啥我会收到“不允许主机 '192.168.1.220' 连接到此 MySQL 服务器”? [复制]
std::cout 一个 null char* 指针如何中止程序? [复制]
为啥我会收到 ValueError: could not convert string to float in Python? [复制]