重载
print << "Some text" << i << endl;
实际上分别为“Some text”、i 和 endl 调用 print.operator
print << "Other text" << i+1 << endl;
那么你可能会得到:
"Some TextOther Text65\n\n"
处理它最简单的方法是先输出到字符串流,然后使用普通的打印函数打印被锁定的互斥锁保护的整个东西:
stringstream ss;
ss <<"Some text" << i << endl;
print(ss.str());
如果您坚持直接使用流,那么流仅在收到刷新指令时才实际写入来处理此类事情。 endl 自动刷新流,这是它与 "\n" 不同的方式之一。
然后您实现一个自定义 std::stringbuf 锁定互斥锁并在 sync() 上输出到控制台,然后为每个线程构造一个 ostream 以用作其个人打印输出流。
示例代码:
#include <iostream>
#include <sstream>
#include <mutex>
#include <thread>
#include <string>
// Increase risk of race condition if one can be triggered.
char slow_get_ch(char ch)
{
for (unsigned int i = 0; i < 10000; ++i)
{
for (unsigned int j = 0; j < 10000; ++j)
{
}
}
return ch;
}
class print_buf : public std::stringbuf
{
std::mutex& mtx_;
public:
print_buf(std::mutex& mtx)
:
mtx_(mtx)
{
}
protected:
int sync() final
{
std::unique_lock<std::mutex> lck(mtx_);
std::string val = this->str();
std::cout << val;
this->str("");
return 0;
}
};
void print_worker(std::ostream* print_stream_ptr,char ch)
{
std::ostream& print = *print_stream_ptr;
// Print 5 lines of 20 times ch.
for (unsigned int i = 0; i < 5; ++i) {
for (unsigned int j = 0; j < 20; ++j) {
print << slow_get_ch(ch);
}
print << std::endl;
}
}
int main()
{
std::mutex print_mutex;
print_buf buf1(print_mutex);
print_buf buf2(print_mutex);
print_buf buf3(print_mutex);
std::ostream p1(&buf1);
std::ostream p2(&buf2);
std::ostream p3(&buf3);
std::thread t1(print_worker, &p1, 'a');
std::thread t2(print_worker, &p2, 'b');
std::thread t3(print_worker, &p3, 'c');
t1.join();
t2.join();
t3.join();
return 0;
}