线程库的奇怪行为

时间:2014-11-28 11:46:26

标签: c++ multithreading c++11 inputstream outputstream

我不知道这个主题是否与std :: thread库或流有关。看看下面的例子:

#include <thread>
#include <iostream>

void read(){
    int bar;
    std::cout << "Enter an int: ";
    std::cin >> bar;
}

void print(){
    std::cout << "foo";
}

int main(){
    std::thread rT(read);
    std::thread pT(print);
    rT.join();
    pT.join();
    return 0;
}

我不在乎它是否会在执行read()函数之前或之后打印“foo”字符串。困扰我的是,当它在执行print()函数之前要求输入时,它实际上会挂起执行。我必须单击“输入”或用一些数据提供std :: cin才能看到“foo”字符串。您可以在下面看到该程序行为的三种可能方案:

1.
>> Enter an int: //here I've clicked enter
>> foo
>> 12 //here I've written "12" and clicked enter
//end of execution

2.
>> fooEnter an int: 12 //here I've written "12" and clicked enter
//end of execution

3.
>> Enter an int: 12 //here I've written "12" and clicked enter
>> foo
//end of execution

如您所见,有时我必须单击Enter才能看到“foo”字符串。在我看来,它应该每次打印,因为它是在一个单独的线程中启动。也许std :: cin以某种方式阻止了std :: cout?如果是,那我该怎么办?

1 个答案:

答案 0 :(得分:7)

这是完全正常的,默认情况下会缓存到std::cout的输出。 coutcin绑定,因此当您从cin开始阅读或按回车键时,cout缓冲区会刷新并显示在屏幕上。

可能发生的事情是第一个线程写入其输出,它被缓冲,然后等待输入,刷新输出缓冲区(所以你看到"Enter an int:")然后第二个线程写入它的输出,但它坐在在缓冲区中,直到读取输入,再次刷新输出。

您可以通过手动刷新缓冲区来强制第二个线程立即输出:

 std::cout << "foo" << std::flush;

这可能会导致"fooEnter an int:""Enter an int:foo",但您不需要在出现"foo"之前按Enter键。