鉴于:
1)C++03标准没有以任何方式解决线程的存在
2) C++03 标准将其留给实现来决定是否std::string
应该在其复制构造函数中使用 Copy-on-Write 语义
3)写时复制语义通常会导致多线程程序中不可预测的行为
我得出以下看似有争议的结论:
您根本无法在多线程程序中安全且可移植地使用 std::string
显然,没有任何 STL 数据结构是线程安全的。但至少,以 std::vector 为例,您可以简单地使用互斥体来保护对向量的访问。对于使用 COW 的 std::string 实现,如果不编辑供应商实现深处的引用计数语义,您甚至无法可靠地做到这一点。
现实世界的例子:
在我的公司,我们有一个多线程应用程序,它已经过彻底的单元测试并通过 Valgrind 运行了无数次。该应用程序运行了几个月,没有出现任何问题。有一天,我在另一个版本的 gcc 上重新编译该应用程序,突然间我总是遇到随机的段错误。 Valgrind 现在在 std::string 复制构造函数中报告 libstdc++ 深处的无效内存访问。
那么解决办法是什么呢?嗯,当然,我可以 typedefstd::vector<char>
作为一个字符串类 - 但实际上,这很糟糕。我还可以等待 C++0x,我祈祷它会要求实现者放弃 COW。或者,(颤抖),我可以使用自定义字符串类。我个人总是抱怨开发人员在现有的库可以很好地工作时实现自己的类,但老实说,我需要一个字符串类,我可以确定它没有使用 COW 语义;而 std::string 根本不能保证这一点。
我说得对吗std::string
根本无法可靠使用at all在可移植的多线程程序中?什么是好的解决方法?
您无法在多线程程序中安全且可移植地执行任何操作。不存在可移植的多线程 C++ 程序这样的东西,正是因为线程将 C++ 所说的有关操作顺序以及修改任何变量的结果的所有内容都抛到了窗外。
标准中也没有任何内容可以保证vector
可以按照你说的方式使用。提供带有线程扩展的 C++ 实现是合法的,例如,在初始化向量的线程之外使用向量会导致未定义的行为。当您启动第二个线程时,您就不再使用标准 C++,并且您必须向编译器供应商询问什么是安全的,什么是不安全的。
如果您的供应商提供了线程扩展,并且还提供了带有 COW 的 std::string (因此)无法使其成为线程安全的,那么我认为目前您的论点是与您的供应商有关,或者是与线程扩展有关,而不是与 C++ 标准。例如,可以说 POSIX 应该在使用 pthread 的程序中禁止使用 COW 字符串。
您可以通过使用单个互斥体来确保安全,在进行任何字符串突变以及对作为副本结果的字符串的任何读取时使用该互斥体。但是您可能会在该互斥体上遇到严重的争用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)