一般来说,我假设流是不同步的,这取决于用户是否进行适当的锁定。但是,像cout
这样的东西在标准库中会得到特殊对待吗?
也就是说,如果多个线程正在向cout
写入数据,它们会破坏cout
对象吗?我知道即使同步了,你仍然会得到随机交错的输出,但是交错是有保证的吗?也就是说,从多个线程使用cout
是否安全?
这个供应商是依赖的吗?gcc是做什么的?
重要提示:如果你说“是”,请为你的回答提供一些参考资料,因为我需要某种证明。
我也不关心底层的系统调用,这些都很好,但是流在上面增加了一层缓冲层。
发布于 2011-06-17 00:23:04
这是一个很好的问题。
首先,C++98/C++03没有“线程”的概念。因此,在那个世界里,这个问题是没有意义的。
那C++0x呢?看看Martinho's answer (我承认这让我很惊讶)。
C++0x之前的具体实现如何?好吧,举个例子,这里是来自GCC 4.5.2 ("streambuf“header)的basic_streambuf<...>:sputc
的源代码:
int_type
sputc(char_type __c)
{
int_type __ret;
if (__builtin_expect(this->pptr() < this->epptr(), true)) {
*this->pptr() = __c;
this->pbump(1);
__ret = traits_type::to_int_type(__c);
}
else
__ret = this->overflow(traits_type::to_int_type(__c));
return __ret;
}
显然,这不会执行锁定。xsputn
也是如此。这绝对是cout使用的streambuf类型。
据我所知,libstdc++没有执行任何流操作的锁定。我不会期望任何东西,因为那会很慢。
因此,在这种实现中,很明显,两个线程的输出可能会相互损坏(而不仅仅是交错)。
这段代码会破坏数据结构本身吗?答案取决于这些函数可能的交互作用;例如,如果一个线程试图刷新缓冲区,而另一个线程试图调用xsputn
或其他什么,会发生什么。这可能取决于编译器和CPU如何决定对内存加载和存储进行重新排序;这需要仔细分析才能确定。它还取决于当两个线程试图并发修改同一位置时CPU执行的操作。
换句话说,即使它碰巧在您当前的环境中运行良好,当您更新任何运行时、编译器或CPU时,它也可能会崩溃。
执行摘要:“我不会”。构建一个执行正确锁定的日志记录类,或者移到C++0x。
作为一个较弱的替代方案,您可以将cout设置为unbuffered。很可能(尽管不能保证)会跳过所有与缓冲区相关的逻辑,直接调用write
。尽管这可能会慢得令人望而却步。
https://stackoverflow.com/questions/6374264
复制相似问题