String copy on write 引发的线程不安全

简介: <br><br>    一个string对象的读操作是线程安全的么?答案是否定的。读取一个string在某些情况下是线程不安全的。这是为什么呢?原因就是string在优化存储空间时采用的策略cow。<br><br><br> 什么是cow<br><p>     Cow 是copy on write的缩写。String 为了减少内存拷贝,当两个string对象的内容相同时,他们指向同一块内


   一个string对象的读操作是线程安全的么?答案是否定的。读取一个string在某些情况下是线程不安全的。这是为什么呢?原因就是string在优化存储空间时采用的策略cow。


什么是cow

     Cow 是copy on write的缩写。String 为了减少内存拷贝,当两个string对象的内容相同时,他们指向同一块内存空间,并通过引用计数来表示有多少对象引用了这块内存。当其中某个string对象的内容发生改变时,string会先重新分配一块空间,把原来的内容拷贝到新空间,原来的空间的引用计数减去1。


什么情况下引发cow

      当程序判断string对象要改变时,就会引发cow。一种比较少见的情况就是,程序获得了string对象的非const引用,那么程序无法判断在接下来的操作中是否会改变这个string对象。所以会触发cow操作。一个典型的例子是string::operator[], 当一个非const对象调用[]操作符时,实际上获得的是对象的非const引用,于是引发了cow。


危害
      上边的operator[],如果只是为了读取字符串的话,那么我们期望这个操作应该是线程安全的。但实际上这个读操作包含了写操作,假如另一个线程同时在读这个字符串的话,程序就有可能在这里使内存写坏。为了解决这个问题,必须给string对象限定为const.


我在产品中发现了这个问题,为了调查这个问题花费了3周的时间,并在第四周时从理论上解释通了这个原因。

目录
相关文章
|
4月前
|
存储 C++ 索引
【C++STL基础入门】深入浅出string类的比较(compare)、复制(copy)
【C++STL基础入门】深入浅出string类的比较(compare)、复制(copy)
|
编译器 C语言 C++
C++从入门到精通(第七篇) :string类的讲解和模拟实现 (copy)
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。
190 0
C++从入门到精通(第七篇) :string类的讲解和模拟实现 (copy)
|
29天前
|
存储 安全 Java
【JAVA基础】String、StringBuilder和StringBuffer的区别——巨详细
String是不可变的,StringBuilder和StringBuffer是可变的。而StringBuffer是线程安全的,而StringBuilder是非线程安全的。
|
19天前
|
存储 XML 缓存
Java字符串内幕:String、StringBuffer和StringBuilder的奥秘
Java字符串内幕:String、StringBuffer和StringBuilder的奥秘
19 0
|
30天前
|
Java
String类中的一些常用方法(JAVA)
字符串比较方法: boolean equals(Object anObject):  int compareTo(String s): int compareToIgnoreCase(String str) 字符串查找方法: char charAt(int index): int indexOf(int ch):  int indexOf(int ch, int fromIndex): int indexOf(String str): int indexOf(String str, int fromIndex): int lastIndexOf(int ch): int
46 0
|
2月前
|
安全 Java 调度
Java基础面试,String,StringBuffer,StringBuilder区别以及使用场景
* String是final修饰的,不可变,每次操作都会产生新的对象。 * StringBuffer和StringBuilder都是在原对象上进行操作 * StringBuffer是线程安全的,StringBuilder是线程不安全的。 * StringBuffer方法是被synchronized修饰的
|
7天前
|
Java
百度搜索:蓝易云【Java中如何向一个string类型的数组中添加数据】
在上述代码中,我们首先创建一个新的String数组 `newArray`,长度为原数组 `originalArray`的长度加1。然后,通过循环将原数组中的元素复制到新数组中。最后,将新数据 `newData`添加到新数组的末尾。现在,`newArray`就包含了原数组的所有元素,并且在末尾添加了新的数据。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
8 0
|
19天前
|
安全 Java 索引
Java中的字符串String
Java中的字符串String
33 0
|
1月前
|
安全 Java 索引
java中两个String字符串比较去重
java中两个String字符串比较去重
12 0