c++ - 来自多个线程的 std::cout

标签 c++ multithreading c++17 stdout mutex

我有一个应用程序,我在其中以并行工作线程执行昂贵的计算。为简单起见,我直接从这些线程将结果写入标准输出。

在我更改一些内容以尝试使代码运行得更快之前,它工作得很好。首先,我用 "\n"替换了 std::endl 以防止在每一行之后刷新。我在主程序的 init 部分添加了以下几行:

    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);

工作线程代码的基本结构如下所示:

while(true) {
    // get data from job queue, protected by unique_lock on std::mutex

    // process the data

    // print results
    {
        std::lock_guard<std::mutex> lk(outputMutex_);
        std::cout << "print many results" << "\n"; // was originally std::endl
    }
}

自从这次“优化”后, worker 的产出偶尔会“混”。即互斥量没有达到预期目的。

为什么会这样?我的理解是只有一个 stdout 流缓冲区,并且数据按顺序到达相应的缓冲区,即使在释放互斥锁之前没有从该缓冲区刷新输出。但似乎并不是这样……

(我意识到在单独的线程中生成输出可能会更好,但是我需要使用另一个队列传回这些结果,这在这里似乎没有必要)

更新:可能我的帖子不够清楚。我不关心结果的顺序。问题是(对于上面的例子)而不是这个:

print many results
print many results
print many results

我有时会:

print many print many results
results
print many results

outputMutex_ 是所有工作线程共享的静态成员。

最佳答案

您正在通过多个线程访问 cout。对其队列的访问受互斥量保护,但需要刷新。这不会自动发生(总是至少 :) )

std::endl 刷新 cout,'\n' 不刷新

或者,您可以使用 std::flush 告诉 cout 刷新:

https://en.cppreference.com/w/cpp/io/manip/flush

尝试:

while(true) {
    // get data from job queue, protected by unique_lock on std::mutex

    // process the data

    // print results
    {
        std::lock_guard<std::mutex> lk(outputMutex_);
        std::cout << "print many results" << "\n"; // not flushed
        std::cout << std::flush; // flushed!
        std::cout << "print something else" << std::endl; // flushed!
    }
}

更多关于: https://stackoverflow.com/a/22026764/13735754

关于c++ - 来自多个线程的 std::cout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62347686/

相关文章:

c++ - pthread_create 参数函数指针

c++ - 取决于模板类型参数的字符串文字?

vector 的 C++ vector

c# - 为什么 AsyncLocal<T> 传播到子线程而 ThreadLocal<T> 不传播?

c++ - 函数指针数组的类模板参数推导适用于 clang,但不适用于 gcc

c++ - 如何使 `short-circuit evaluation` 在 `fold expressions` 中也可用?

c++ - 内联函数和 __thiscall __cdecl Bjarne String 示例

java - 如何停止通过实现可运行接口(interface)创建的线程?

c# - 当某些 WaitHandle 正在调用 WaitOne 时,您如何关闭应用程序?

c++ - 当 std::uint_fast32_t 在 GCC 中为 4 字节时,std::mt19937 失败