我们都知道:
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
那么,为什么StringBuilder不是线程安全的。
分析
StringBuilder和StringBuffer的内部实现跟String类一样,都是通过一个char数组存储字符串的,不同的是String类里面的char数组是final修饰的,是不可变的,而StringBuilder和StringBuffer的char数组是可变的。
首先,我们可以了解一下StringBuffer和StringBuilder的异同。
String,StringBuilder以及StringBuffer这三个类之间的区别
下面,我们通过一段代码来看看如果我们多线程操作了StringBuilder对象会发生什么。
1 | public class StringBuilderTest { |
在这段代码中,我们创建了10个进程,每个进程循环10000次向StringBuilder对象stringBuilder
和StringBuffer对象stringBuffer
中append字符a、b。
如果其中没有出错的话,最后的输出字符串的长度应该是100000。
但实际上的结果是:
那么为什么结果会和预期的值不一样呢。
我们先来看一看StringBuilder的append()方法:
StringBuilder的append()方法调用的是父类AbstractStringBuilder的append()方法:
我们可以看到,其中 count += len 不是一个原子操作。当多个线程同时执行的时候,取得的count值都是一样的,但是执行完加法后赋值给count,count的值只增加了1,但是实际上却是多个线程同时执行了这一步,这就是为什么结果比预计值要小的原因。
同理就可以分析出StringBuffer为什么是线程安全的了。
最后更新: 2019年10月15日 22:43
原始链接: http://leiii33.github.io/2019/09/15/为什么StringBuilder不是线程安全的/