这是我第一次尝试编写多线程 C++ 代码,它似乎引发了一场数据竞赛。这是完整的文件。它被编译为:g++ -pthread foo.cpp
#include <iostream>
#include <iomanip>
#include <thread>
const int SIZE = 5;
void mult(int x, int y) {
std::cout.width(3);
std::cout << std::right << x * y << "* ";
}
void add(int x, int y) {
std::cout.width(3);
std::cout << std::right << x + y << "+ ";
}
int main() {
int a = 0;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
std::thread first(mult, i, j);
std::thread second(add, i, j);
first.join();
second.join();
std::cout << " | ";
}
std::cout << "\n";
}
return 0;
}
每次运行时,输出都会以不可重现的方式进行加扰,例如:
0* 0+ | 0* 1+ | 2 0+ * | 0* 3+ | 0* 4+ |
0* 1+ | 1* 2+ | 2* 3+ | 3* 4+ | 4* 5+ |
0* 2+ | 2* 3+ | 4* 4+ | 6* 5+ | 8* 6+ |
0* 3+ | 3 4* + | 6* 5+ | 9* 6+ | 12* 7+ |
0* 4+ | 4* 5+ | 8* 6+ | 12* 7+ | 16* 8+ |
或者
0* 0+ | 0* 1+ | 0* 2+ | 0* 3+ | 0* 4+ |
0* 1+ | 1* 2+ | 2* 3+ | 3* 4+ | 4* 5+ |
0* 2+ | 2* 3+ | 4* 4+ | 6* 5+ | 8* 6+ |
0* 3+ | 3* 4+ | 6* 5+ | 9* 6+ | 12* 7+ |
0* 4+ | 4* 5+ | 8* 6+ | 12* 7+ | 16* 8+ |
有没有办法解决这个问题?我从中学到了很多关于 cout 对象的知识,但是规则是否一次只允许一个线程访问 cout,尤其是在使用 iomanip 时?
编辑:据我了解: http : //www.cplusplus.com/reference/iomanip/setw/ 以这种方式使用 iomanip 可能会导致数据竞争。所以问题是,不应该尝试这样做吗?是否应该创建每个要 cout 的线程,执行其业务,然后加入?(即根本没有线程),就是这样?如果是这样,那很好,并发的主要思想是让程序打开多个并发的 fstream 对象,这样用户就不必等待,一个线程 cout 就可以了。我要问的是,这是标准方法吗?