【发布时间】:2018-11-06 03:26:54
【问题描述】:
在多个线程中使用 cout 可能会导致交错输出。
所以我尝试用互斥锁来保护 cout。
以下代码使用 std::async 启动 10 个后台线程。当一个线程启动时,它会打印“Started thread ...”。 主线程按照后台线程的创建顺序迭代它们的未来,并在相应线程完成时打印出“Done thread ...”。
输出已正确同步,但在一些线程启动和一些线程完成后(见下面的输出),发生死锁。所有后台线程都离开了,主线程正在等待互斥锁。
死锁的原因是什么?
当 print 函数离开或 for 循环的一次迭代结束时,lock_guard 应该解锁互斥锁,以便其中一个等待线程能够继续。
为什么所有的线程都饿死了?
代码
#include <future>
#include <iostream>
#include <vector>
using namespace std;
std::mutex mtx; // mutex for critical section
int print_start(int i) {
lock_guard<mutex> g(mtx);
cout << "Started thread" << i << "(" << this_thread::get_id() << ") " << endl;
return i;
}
int main() {
vector<future<int>> futures;
for (int i = 0; i < 10; ++i) {
futures.push_back(async(print_start, i));
}
//retrieve and print the value stored in the future
for (auto &f : futures) {
lock_guard<mutex> g(mtx);
cout << "Done thread" << f.get() << "(" << this_thread::get_id() << ")" << endl;
}
cin.get();
return 0;
}
输出
Started thread0(352)
Started thread1(14944)
Started thread2(6404)
Started thread3(16884)
Done thread0(16024)
Done thread1(16024)
Done thread2(16024)
Done thread3(16024)
【问题讨论】:
-
在锁保护之前在变量中检索未来的结果
f.get(); -
std::cout 是线程安全的,因此可以无锁地使用它并且仍然可以按预期输出:stackoverflow.com/a/15034536/985296
-
相关,
ostringstream可能不会遇到这些问题。即ostringstream oss; oss << "Done thread" << f.get() << "(" << this_thread::get_id() << ")" << endl; cout << oss.str();另见Is cout synchronized/thread-safe? -
感谢您的宝贵回答。错误是在锁定互斥锁时使用 f.get() 。 ostringstream 版本也可以正常工作。
标签: c++ multithreading concurrency mutex deadlock