0


Java 看完快去给面试官说说为啥StringBuilder线程不安全

从 StringBuilder的源码维度去解读为啥导致线程不安全 。

先回顾一下我曾写过的类似 线程不安全的文章:

面试官问 : ArrayList 不是线程安全的,为什么 ?(看完这篇,以后反问面试官)

面试官问 : SimpleDateFormat 不是线程安全的,你有了解过吗?

如果有去看过,你的心,是很明亮的。
(这个线程不安全,肯定又是有哪个公共变量在搞事。)

好的 ,事不宜迟,我们开始。

StringBuilder 线程不安全,直接锁定 append方法 。

源码:

(好了,结束了。 就是这些公共变量搞事情。)

哪里导致不安全?

看到这行代码没 ?

非原子操作 ** count += len;**

简单举个最简单的例子,去看看这个非原子操作的线程并发的场景。

AB两个线程当前count (公共全局变量) 都是 100 , 而 都传入了 str = ‘x’ ,也就是 int len = str.length(); len为1.

这时候 都去执行 ** count += len; **

AB 两个线程 拿到count 都是 100, 然后共同执行 +1, 然后共同拿到结果 count=101 。

这时候,已经出现问题了 。 正常应该是后者拿到count为102 .

所以说,如果线程并发多,不只是AB,而是ABCDEFG, 那 count的值, 都不准成啥样了。。。

那么继续看这个 ** count += len; ** 的上面一行

str.getChars(0, len, value, count);

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
    if (srcBegin < 0) {
        throw new StringIndexOutOfBoundsException(srcBegin);
    }
    if (srcEnd > value.length) {
        throw new StringIndexOutOfBoundsException(srcEnd);
    }
    if (srcBegin > srcEnd) {
        throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
    }
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

char dst[] 是 传入的 value[]

而dstBegin 就是传入count

简单解释:

正常一个个元素新增, value[] 长度到 9, 那么 count就是10 ,代表dstBegin从 第10个位置新增元素(有序正常进行) 。

想想一种情景。

就是 比如 这个数组当前最大容量是10 ,然后 即将新增元素后本身得到的count是11, 11-10>0

是需要扩容的,

这样扩容之后,这个函数的意义就很对。(保证正常扩容,到了临界点就扩容,这样后面的线程新增元素就包妥了)

**但是! 但是!但是! **

**如果 并发出现了! **

也就是 说 后面的B线程本身拿到的count值 是A线程执行完+1的才对!

但是呢,因为并发,AB 线程拿到的count值是一样的,都没触发扩容,相当

于 ensureCapacityInternal这个函数, 都绕过去了, 没扩容 。

所以B线程执行到 str.getChars(0, len, value, count);

这时候就会出现 dst 传入的 value[] 和 dstBegin 传入的count 是一样的。。。

就是说 数组容量塞满了(比如是10),然后你告诉我 下一个新增元素的位置 也是10, 那于是乎,当然就抛出异常 数组越界 ArrayIndexOutOfBoundsException 咯。

好了,该篇就到这。


本文转载自: https://blog.csdn.net/qq_35387940/article/details/141711440
版权归原作者 小目标青年 所有, 如有侵权,请联系我们删除。

“Java 看完快去给面试官说说为啥StringBuilder线程不安全”的评论:

还没有评论