5

我是 Boost 线程的新手,我对如何从多个线程执行输出感到困惑。我有一个简单的 boost::thread 从 9 倒数到 1;主线程等待然后打印“LiftOff..!!”

#include <iostream>
#include <boost/thread.hpp>
using namespace std;

struct callable {
    void operator() ();
};

void callable::operator() () {
    int i = 10;
    while(--i > 0) {
        cout << "#" << i << ", ";
        boost::this_thread::yield();
    }
    cout.flush();
}

int main() {
    callable x;
    boost::thread myThread(x);

    myThread.join();

    cout << "LiftOff..!!" << endl;

    return 0;
}

问题是我必须在我的线程中使用明确的“cout.flush()”语句来显示输出。如果我不使用flush(),我只会得到“LiftOff!!” 作为输出。

有人可以告诉我为什么我需要明确使用 flush() 吗?

4

4 回答 4

5

这与线程无关,因为 cout 通常会在每个线程的基础上进行缓冲,并且仅在实现决定时才输出 - 所以在线程中,输出只会出现在特定于实现的基本上 - 通过调用 flush 你强制缓冲区被冲洗。

这会因实现而异——通常是在一定数量的字符之后或发送新行时。

我发现多个线程也写入相同的流或文件大多是可以的 - 只要输出尽可能原子地执行。我不建议在生产环境中使用它,因为它太不可预测了。

于 2012-05-28T13:14:53.053 回答
3

这种行为似乎取决于操作系统特定的 cout 流实现。我猜在你的情况下,cout 上的写操作被缓冲到一些线程特定的内存中,并且 flush() 操作强制它们被打印在控制台上。我猜是这样,因为 endl 包括调用 flush() 操作,并且 main 函数中的 endl 即使在线程加入后也看不到您的更改。

顺便说一句,无论如何最好将输出同步到线程之间共享的 ostream,否则您可能会看到它们混合在一起。我们为使用后台线程将日志消息写入关联的 ostream 的日志记录类这样做。

于 2012-05-28T12:59:37.103 回答
0

鉴于您的消息长度很短,没有任何理由应该在没有刷新的情况下出现。(不要忘记这std::endl相当于<< '\n' << std::flush。)

于 2012-05-28T13:00:20.933 回答
0

在有和没有冲洗(gcc 4.3.2 boost 1.47 Linux RH5)的情况下,我得到了询问的行为

我假设您的 cygwin 系统选择std::cout使用关联std::streambuf的 . 我认为这是特定于实现的。由于flushor endl 仅强制缓冲区刷新到其操作系统控制的输出序列,因此线程的 cout 对象保持缓冲。

在线程之间共享引用ostream应该可以解决问题。

于 2012-05-28T14:44:48.420 回答