StringBuilder线程不安全原因——简单理解

例子:

多线程操作StringBuilder对象:

public class StringBuilderDemo{
    public static void main(String[] args) throws InterruptedException{
        StringBuilder sBuilder = new StringBuilder();
        for(int i=0;i<10;i++){
            new Thread(new Runnable(){
                @Override
                public void run(){
                    for(int j=0;j<1000;j++){
                        sBuilder.append("a");
                    }
                }
            }).start();
        }
        Thread.sleep(100);
        System.out.println(sBuilder.length());
    }
}

运行结果:7346

问题1:为什么不是10000(中心思想:覆盖)

StringBuilder的两个成员变量:

//存储字符串的具体内容
char[] value;
//已经使用的字符数组的数量
int count;

StringBuilder的append()方法调用父类“AbstractStringBuilder”的append()方法:

public AbstractStringBuilder append(String str){
    if(str==null){
        return appendNull();
    }
    int len = str.length();
    //验证原数组是否需要扩容
    ensureCapacityInternal(count + len);
    //拼接元素
    str.getChars(0,len,value,count);
    //记录拼接后的元素个数(注意是个数)
    count += len;
    return this;
}

找到count += len,假设count为10,len值为1,两个线程同时执行到这里,拿到的count值都为10,结果两个线程执行完后的count值为11,而不是12,而且getChars方法被同时执行(可理解为:拼接第x个元素时,这几个线程同时运行导致覆盖,都往一个地方同时放一样的东西可不就变成一个了嘛)。

问题2:抛异常:ArrayIndexOutOfBoundsException(中心思想:一个数组满了,你非得再加一个元素,人家还没有位置给你,可不得异常嘛)

条件1:

public AbstractStringBuilder append(String str){
    if(str==null){
        return appendNull();
    }
    int len = str.length();
    //验证原数组是否需要扩容
    ensureCapacityInternal(count + len);
    //拼接元素
    str.getChars(0,len,value,count);
    //记录拼接后的元素个数(注意是个数)
    count += len;
    return this;

条件2:

  //建立一个有内容的初始化数组
  String Str1 = new String("www.runoob.com");
  // 下标:0 1 2 3 4
  char[] Str2 = new char[5];
  //到此 Str2的前三个元素:0——r 1——u 2——n 3——o 4——没有
  Str1.getChars(4,8,Str2,0);
  
  //两个线程 分别 拿出A 和 B  放进Str2,分别放在 下标4和5。
  "ABCD".getChars(0,1,Str2,4);//线程1
  "ABCD".getChars(1,2,Str2,5);//线程2
  //报错(人家就剩一个位置是4 线程1先使用了,线程2无处放,又不让扩容,故报错)

两个线程都走完了条件1的ensureCapacityInternal方法,都说不需要扩容,接着走getChars方法,唉呀妈呀:线程2这个时候掉链子了,不走了,线程1接着走,老1走完 把他手里的元素放在了最后一个位置,数组满了,然后登记一下count为5,这个时候老2醒了,但是已经不能再回去进行扩容数组了啊,因为刚才都说了不需要扩容,这咋整 ?数组满了呀,又不能在扩容,那就抛出异常呗!!!(例如条件2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值