鉴于:
1)C++ 03标准没有以任何方式解决线程的存在
2)C++ 03标准让实现决定是否std::string
应该在其拷贝构造函数中使用Copy-on-Write语义
3)Copy-on-Write语义经常导致多线程程序中不可预测的行为
我得出以下看似有争议的结论:
您无法在多线程程序中安全且可移植地使用std :: string
显然,没有STL数据结构是线程安全的.但至少,使用std :: vector,您可以简单地使用互斥锁来保护对向量的访问.使用使用COW的std :: string实现,如果不在供应商实现中深入编辑引用计数语义,您甚至无法可靠地执行此操作.
现实世界的例子:
在我的公司,我们有一个多线程应用程序,经过彻底的单元测试,无数次通过Valgrind.该应用程序运行了几个月,没有任何问题.有一天,我在另一个版本的gcc上重新编译应用程序,突然之间我总是得到随机的段错误.Valgrind现在在std :: string复制构造函数中报告libstdc ++中的无效内存访问.
那么解决方案是什么?好吧,当然,我可以将typedef std::vector<char>
作为一个字符串类 - 但实际上,这很糟糕.我还可以等待C++ 0x,我祈祷将要求实现者放弃COW.或者,(颤抖),我可以使用自定义字符串类.我个人总是反对在预先存在的库可以正常运行时实现自己的类的开发人员,但老实说,我需要一个字符串类,我可以肯定它不使用COW语义; 和std :: string根本不保证.
我是不是正确的,std::string
根本无法可靠地使用在所有便携式,多线程程序?什么是好的解决方法?
Ste*_*sop 11
在多线程程序中,您无法安全且可移植地执行任何操作.没有可移植的多线程C++程序,正是因为线程抛出了C++关于操作顺序的所有内容,以及修改任何变量的结果.
标准中也没有任何内容可以保证vector
可以按照您的说法使用.提供带有线程扩展的C++实现是合法的,其中,例如,在初始化线程之外的任何使用向量会导致未定义的行为.您启动第二个线程的那一刻,您不再使用标准C++,您必须向您的编译器供应商寻求安全和不安全的东西.
如果你的供应商提供了一个线程扩展,并且还提供了一个带有COW的std :: string,因此不能使其成为线程安全的,那么我认为你的论点暂时与你的供应商或者线程扩展有关,而不是使用C++标准.例如,可以说POSIX应该在使用pthreads的程序中禁止COW字符串.
您可以通过使用单个互斥锁来保证安全,您可以在执行任何字符串突变时使用该互斥锁,以及任何字符串读取都是复制的结果.但是你可能会对这个互斥锁进行严厉的争论.
你是对的.这将在C++ 0x中修复.现在你必须依赖你的实现文档.例如,最近的libstdc ++ Versions(GCC)允许您使用字符串对象,就好像 没有字符串对象与另一个字符串对象共享其缓冲区一样.C++ 0x强制库实现保护用户免受"隐藏共享".
鉴于标准没有提及内存模型并且完全不知道线程,我想说你不能肯定地假设每个实现都不是牛,所以不,你不能
除此之外,如果您了解您的工具,大多数实现将使用非母牛字符串来允许多线程。