2012-05-28 55 views
5

我是Boost线程的新手,我坚持如何从多个线程执行输出。 我有一个简单的boost :: thread从9减1;主线等待,然后打印“LiftOff .. !!”BOOST线程:cout行为

#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()吗?

+1

对于我来说,使用或不使用'flush()'(linux 3.0.6,gcc 4.5.3,boost 1.46)对我来说也是一样。 – delicateLatticeworkFever

+0

FWIW,我在Win7x64(MSVC10)上测试了你的程序,并且它在没有flush()的情况下打印出数字。 Om你测试了哪个平台? –

+0

@KonradRudolph:“竞争条件”不会创建两个单独的标准输出缓冲区,这是唯一可以想象的解释为什么在等待联接线程后main中的endl没有刷新。 (更不用说:这里根本就没有“竞争条件”,只有两个线程,另一个在等待。) – delicateLatticeworkFever

回答

5

这不是专门与线程相关的,因为cout通常会以每个线程为基础进行缓冲,并且只有在实现决定时才会输出 - 因此在线程中输出只会出现在具体实现的基础上 - 通过调用flush来强制缓冲区被刷新。

这会因不同的实现而有所不同 - 通常它会在一定数量的字符之后或发送新行时发生。

我发现多个线程写太多相同的流或文件大多是确定 - 提供的输出是尽可能原子执行。这不是我在生产环境中推荐的,因为它太难预测。

3

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

顺便说一句,将输出同步到线程之间共享的ostream是一个好主意,否则您可能会看到它们交错。我们这样做是为了使用后台线程的日志类将日志消息写入关联的ostream。

+0

我很惊讶地发现,为每个进程实现多个标准输出缓冲区是标准允许的,等等,但这似乎是唯一可能的解释。当然,只有OP似乎已经观察到了这一点o_O – delicateLatticeworkFever

+0

@goldilocks:是的同意,所描述的行为也让我感到惊讶!但是,甚至可以超出cout/stdout缓冲区实现,这可以是OS特定的,不是吗?知道哪个操作系统被OP使用会很有趣... –

+0

谢谢makulik。你的推理听起来不错,但是如果cout每个线程有不同的流缓冲区,它真的很奇怪 – Rajat

0

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

0

我得到的问行为与不冲洗(gcc 4.3.2 boost 1.47 Linux RH5

我认为你的cygwin的系统选择实现几个std::cout对象与相关std::streambuf。我假设这是实现特定的。 因为flush或endl只会强制缓冲区刷新到其OS控制的输出序列,所以线程的cout对象将保持缓冲。

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