是std :: string thead-safe与gcc 4.3? [英] Is std::string thead-safe with gcc 4.3?

查看:170
本文介绍了是std :: string thead-safe与gcc 4.3?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个在Linux上运行的多线程程序(使用G ++ 4.3编译),如果你搜索一下,你发现很多关于std :: string的可怕故事不是GCC的线程安全的。这被认为是由于内部使用写入复制,它使用像Helgrind这样的工具造成严重破坏。



我做了一个小程序,复制一个字符串到另一个字符串,如果你检查两个字符串,他们都共享相同的内部_M_p指针。当一个字符串被修改时,指针改变,所以写时复制的东西工作正常。



我担心的是,如果我共享一个字符串(例如将它作为一个对象在两个线程之间的线程安全数据队列中传递)。我已经尝试用'-pthread'选项编译,但似乎没有什么区别。所以我的问题:




  • 有没有办法强制std :: string是线程安全的?我不介意如果禁用写时复制行为来实现这一点。

  • 其他人如何解决这个问题?



我似乎找不到一个确定的答案,所以我希望你们可以帮助我.. / p>

编辑



哇,这么短的答案时间。谢谢!我肯定会使用杰克的解决方案,当我想禁用COW。但现在的主要问题是:我真的必须禁用COW?还是为COW线程安全的记帐?我目前正在浏览libstdc ++源文件,但是这需要花费一些时间来确定...



编辑2

OK浏览libstdc ++源代码,我在libstd ++ - v3 / include / bits / basic_string.h中找到了这样的代码:

  _CharT * 
_M_refcopy()throw()
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if(__builtin_expect(this!=& _S_empty_rep ,false))
#endif
__gnu_cxx :: __ atomic_add_dispatch(& this-> _M_refcount,1);
return _M_refdata();
} // XXX MT

因此,计数器...



结论



我将sellibitze的评论标记为答案因为我认为我们得出的结论是,这个领域目前还没有解决。为了规避COW行为,我建议杰克·劳埃德的答案。感谢大家进行有趣的讨论!

解决方案

主题不是标准的一部分。但我不认为任何供应商可以逃避没有使std :: string线程安全,现在。注意:线程安全有不同的定义,我的可能不同于您的。当然,默认情况下保护一个像std :: vector这样的容器来并发访问是没有意义的,即使你不需要它。这将违背不支付你不使用的东西的C ++精神。如果用户想要在不同线程之间共享对象,那么用户应该始终负责同步。这里的问题是,一个库组件是否使用和共享一些隐藏的数据结构,可能导致数据竞争,即使功能应用于不同的对象从用户的角度。



C ++ 0x草案(N2960)包含数据竞争避免部分,该部分基本上说,库组件可以访问当且仅当它主动避免可能的数据竞争时从用户隐藏的共享数据。听起来像一个copy-on-write实现的std :: basic_string必须是安全的w.r.t.多线程作为另一个实现,其中内部数据从不在不同的字符串实例之间共享。



我不能100%确定libstdc ++是否已经处理了。我认为它。当然,请查看文档


I'm developing a multithreaded program running on Linux (compiled with G++ 4.3) and if you search around for a bit you find a lot of scary stories about std::string not being thread-safe with GCC. This is supposedly due to the fact that internally it uses copy-on-write which wreaks havoc with tools like Helgrind.

I've made a small program that copies one string to another string and if you inspect both strings they both share the same internal _M_p pointer. When one string is modified the pointer changes so the copy-on-write stuff is working fine.

What I'm worried about though is what happens if I share a string between two threads (for instance passing it as an object in a threadsafe dataqueue between two threads). I've already tried compiling with the '-pthread' option but that does not seem to make much difference. So my question:

  • Is there any way to force std::string to be threadsafe? I would not mind if the copy-on-write behaviour was disabled to achieve this.
  • How have other people solved this? Or am I being paranoid?

I can't seem to find a definitive answer so I hope you guys can help me..

Edit:

Wow, that's a whole lot of answers in such a short time. Thank you! I will definitely use Jack's solution when I want to disable COW. But now the main question becomes: do I really have to disable COW? Or is the 'bookkeeping' done for COW thread safe? I'm currently browsing the libstdc++ sources but that's going to take quite some time to figure out...

Edit 2

OK browsed the libstdc++ source code and I find something like this in libstd++-v3/include/bits/basic_string.h:

  _CharT*
   _M_refcopy() throw()
   {
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
     if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
            __gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
     return _M_refdata();
   }  // XXX MT

So there is definitely something there about atomic changes to the reference counter...

Conclusion

I'm marking sellibitze's comment as answer here because I think we've reached the conclusion that this area is still unresolved for now. To circumvent the COW behaviour I'd suggest Jack Lloyd's answer. Thank you everybody for an interesting discussion!

解决方案

Threads are not yet part of the standard. But I don't think that any vendor can get away without making std::string thread-safe, nowadays. Note: There are different definitions of "thread-safe" and mine might differ from yours. Of course, it makes little sense to protect a container like std::vector for concurrent access by default even when you don't need it. That would go against the "don't pay for things you don't use" spirit of C++. The user should always be responsible for synchronization if he/she wants to share objects among different threads. The issue here is whether a library component uses and shares some hidden data structures that might lead to data races even if "functions are applied on different objects" from a user's perspective.

The C++0x draft (N2960) contains the section "data race avoidance" which basically says that library components may access shared data that is hidden from the user if and only if it activly avoids possible data races. It sounds like a copy-on-write implementation of std::basic_string must be as safe w.r.t. multi-threading as another implementation where internal data is never shared among different string instances.

I'm not 100% sure about whether libstdc++ takes care of it already. I think it does. To be sure, check out the documentation

这篇关于是std :: string thead-safe与gcc 4.3?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆