绑定到const&参数的实参常量性是否会引发线程不安全?
C++并发修改std::string时length()的行为问题
先看你给出的代码:
/* whatever */ foo(std::string const& s) { // stuff auto L = s.length(); int i{/* init based on L */}; while (i < L) { // do other stuff and maybe ++i; } }
你的疑问核心是:如果其他线程并发修改绑定到s的实参,s.length()会不会出现不可预知的变化?答案是——不仅会,而且整个场景属于未定义行为,任何操作结果都不可靠。
具体来说:
std::string本身不是线程安全的容器。当一个线程通过const&读取它,同时另一个线程修改它,这就构成了数据竞争,直接违反C++标准的规定,程序的行为完全不可预测。- 不管你是缓存
L还是每次调用s.length(),都解决不了根本问题:缓存L可能拿到的是修改前的过时长度,直接调用s.length()则可能拿到被修改后的错误值,甚至因为字符串内部结构被并发破坏导致程序崩溃。 - 单线程环境下,去掉
L直接用s.length()是没问题的,但一旦涉及并发修改,两种写法都不安全。
正确的处理方式:
- 必须用同步机制保护这个
std::string的所有读写操作,比如用std::mutex加锁:修改时加锁,读取(包括调用length()、访问字符等)时也加锁,确保同一时间只有一个线程在操作它。 - 或者,给
foo函数传递std::string的副本,这样原字符串的修改不会影响函数内的副本,两种写法都能安全运行。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

