StringBuilder的父类AbstractStringBuilder的**appendNull()**方法
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
其中count为当前char数组容量大小;final char[] value=this.value;此处的复制是无用的,应该并不能将this.val转化为final对象,这里final修饰词最大的作用可能是提示不能将value进行重新赋值。
这里举一个例子,当ThreadA和ThreadB同时调用sb这个对象时,首先扩容ensureCapacityInternal会进行扩容由于Arrays.copyOf方法不是同步的一样会造成多线程异常
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
这里扩容可能会扩大8个char或者4个char,具体原因不细讲。
然后在对value数组进行赋值,最后在执行结束时归还count,可能会有两种情况第一种是ThreadA先归还,ThreadB后归还,第二种情况是ThreadB先归还,无论谁先归还最终count都只会+4。但是由于在执行过程中ThreadA和ThreadB对value[]的赋值可能是交叉进行的,会导致append的值实际不为’null’可能为’nnuu’或者其他情况。如果出现了任意一种多线程异常状况都会导致append的值与’null’不相同,所以都应定为无效的,但是通过c来控制可以让增长的长度为恒定的4,如果不使用int c=count来控制,会使count值增长8。这里想表明的是对于多线程情况下,无论是是不是用c来临时保存count数值都不会让这个appendNull操作变得线程安全起来,但是可以保证在发生多线程不安全的情况下,浪费的空间,也就是扩容的空间最少。
对于多线程出错降低了浪费的扩容空间
依旧未解决多线程错误问题