【问题标题】:Why cout doesn't work with pthreads?为什么 cout 不适用于 pthreads?
【发布时间】:2016-08-22 10:04:33
【问题描述】:

我正在尝试一个简单的程序来测试多线程。我只是在备用线程中打印一系列“x”和“O”。现在,如果我使用 cout ,屏幕上看不到任何输出。如果我使用 fputc 并输出到 stderr ,它工作正常。为什么 cout(输出到标准输出)在这里不起作用?

我的代码如下:

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

using namespace std;

static int count;

void* print_xs(void *unused)
{
    while(1)
    {
        if (count >=100) break;
        if (count%2==0)
        {
            count++;
            cout<<"X=";  // no output here
            fputc('X',stderr); // works !
        }
        else
        {
            sleep(1);
        }
    }
    return NULL;

}


int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,&print_xs, NULL);

    while(1)
    {
        if (count >=100) break;
        if (count%2!=0)
        {
            count++;
            cout<<"O="; // no output here 
            fputc('O',stderr); // works !
        }
        else
        {
            sleep(1);
        }
    }

    pthread_join(tid,NULL);
    return (0);

}

【问题讨论】:

  • 你试过flushstd::cout吗?
  • 尝试打印到stdout。
  • @Nawaz std::cout 是线程安全的。
  • @Galik:是的。自 C++11 以来,它发生了变化。谢谢指正。
  • 另外:你的代码对我有用(Linux GCC 6.1.1)

标签: c++ linux pthreads


【解决方案1】:

由于std::cout 是一个缓冲流,您需要flush 才能将缓冲区发送到标准输出。

试试类似的东西:

cout<< "O=";
cout.flush();

应该可以的。

补充说明

  1. 正如一些 cmets 已经建议您的那样,std::cout 在 C++03 及之前的版本中不是线程安全的 。使用mutex 保护该对象可能很有用。 这可能不是问题,因为 C++11 标准。

FDIS 在 §27.4.1 [iostream.objects.overview] 中说:

多线程并发访问同步(第 27.5.3.4 节)标准 iostream 对象的格式化和未格式化输入(第 27.7.2.1 节)和输出(第 27.7.3.1 节)函数或标准 C 流不应产生数据种族(§1.10)。 [ 注意:如果用户希望避免交错字符,则仍必须同步多个线程对这些对象和流的并发使用。 ——尾注]

这意味着没有 mutex 可以保证对象不会在数据竞争上下文中损坏。但是重叠输出的问题仍然存在。因此,如果您确定每一行都没有被另一个线程重叠打印,那么您仍然需要一个互斥体。

  1. C++11 引入了一个多线程库(通常是 pthread 的包装器)。 Here some reference。看看吧,你会发现它很有用。

【讨论】:

  • 谢谢,但我不明白为什么只有在使用线程时才会出现问题?当我正常使用 cout 时,它会正确显示在标准输出上。
  • 这不是真的。即使在单线程中,您也会得到这种行为。我想你从来没有注意到这一点。我刚刚编写了一个简单的代码,它打印一个字符串 10 次(没有\n):for(...) std::cout &lt;&lt; "something";,然后是调试器,直到程序结束才写入任何内容。 (您也可以尝试,但这取决于特定的实现)。如果您需要,我还可以修改我的答案并向您展示该行为。
  • @vinit 我忘了给你加标签 :)
  • 我明白了,所以 cout 只是一直在缓冲,直到遇到 '\n' 或它被刷新?谢谢,我不知道这个....在 C++ 中总有一些新东西要学:)
  • @vinit 实际上,当遇到'\n' 时,不能保证流被刷新。这就是为什么 std::endl 插入新行字符 '\n' 并刷新流的原因。如果您愿意,可以将答案标记为正确。
猜你喜欢
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 2021-12-04
相关资源
最近更新 更多