使用STL流来简化C++“线程安全”日志记录

ZDNet软件频道 时间:2003-10-30 作者:周靖 译 |  我要评论()
本文关键词:cpp
流是一种强大的数据处理抽象机制,它允许你调用泛型的读/写函数,不必关心数据从什么地方来、到什么地方去。使用流,同样的代码可从控制台、文件、套接字等地方读取数据。C++将流的强大能力与运算符重载合并到一起,为我们提供了>>和<<运算符,以便从流中读取,以及向流中写
本文译自Builder.com,未经许可请勿转载

流是一种强大的数据处理抽象机制,它允许你调用泛型的读/写函数,不必关心数据从什么地方来、到什么地方去。使用流,同样的代码可从控制台、文件、套接字等地方读取数据。

C++将流的强大能力与运算符重载合并到一起,为我们提供了>>和<<运算符,以便从流中读取,以及向流中写入,如清单A所示。

向流中写入通常不是“线程安全”(thread-safe)的。事实上,即便是freadfwrite这样的基元函数,也不要求是线程安全的。不过,使用正确实现的标准模板库(STL)流,不仅能继续发挥流简单易用的特点,还能保证代码的线程安全。另外,你以前使用了<<运算符的代码仍可继续使用,所有线程安全问题都会在幕后解决。

STL流为什么默认不是线程安全的
C++标准没有规定向流中写入是否线程安全,但它通常都不是。这主要是考虑到效率问题。如果向流中的写入是线程安全的,就要求所有public(以及一些protected)函数也是线程安全的。根据STL文档,basic_ostream<>类(所有输出类的基类)有大量public函数。例如以下代码:
for (int idx = 0; idx < 1000000; ++idx) std::cout << idx << ' ';

假如向std::cout的写入是线程安全的,就需要至少200万个锁,这无疑会造成巨大的性能瓶颈。

另外,假如流使用了流缓冲(stream buffers),则缓冲也必须是线程安全的。对一个STL流类进行扩展,还会造成更大的线程安全性能问题。最后,即使STL流是线程安全的,如清单B所示的代码也不能担保生成你所希望的结果。

从表面看,清单B应该在控制台上打印以下结果:
message from thread 1
message from thread 2


但它实际输出的是:
message from message from thread 2
thread 1


这是因为在第一个线程成功打印messagefrom之后,第二个线程将接管控制权,打印它的完整的消息。之后,第一个线程继续打印它尚未完成打印的内容。这个简单的例子演示了假如代码不是线程安全的,可能有什么后果。


百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134