• 为什么说StringBuilder线程不安全?


    简单的回答:因为相对StringBuffer,StringBuilder没有在方法上使用 synchronized 关键字。例如

    StringBuffer :
        @Override
        public synchronized StringBuffer append(String str) {
            toStringCache = null;  //这行是做什么的,有待研究
            super.append(str);
            return this;
        }
    StringBuilder :
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

    再进入 StringBuilder 的 super.append(str);看一看

    public AbstractStringBuilder append(String str) {
            if (str == null)
                return appendNull();
            int len = str.length(); //获得在后缀增加字符串的长度
            ensureCapacityInternal(count + len);// 扩容,如果 扩容为 (当前长度*2)+2 还小于所需要的最小长度空间,那么久 扩容为最小长度空间。当前值得两倍+2 int newCapacity = (value.length << 1) + 2;   
            str.getChars(0, len, value, count);//getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将str 赋值到 value 从count开始
            count += len;//重点就是这一行代码,他不是原子操作,多线程的时候会导致长度count不同步。这样就线程不安全了
            return this;
        }

    下面是demo程序运行结果

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

    如果线程安全,这里结果应该是显示100000的。如果使用StringBuffer就可以避免这个问题

    所以,主要是因为  count += len;这一行代码不是原子操作,

    conut = count +len;多个线程访问count的时候,在内存中就不同步啦

  • 相关阅读:
    Linux Shell常用shell命令
    shell ls
    [转]推荐一些不错的计算机书籍
    What does it mean when you assign [super init] to self?
    保存,读取与多任务处理
    程序媛去过的地方
    读取pcap文件,过滤非tcp包,获取IP及tcp端口信息
    IM实现联系人及联系人分组的数据库设计
    【原创】校园网用户,1个账号2个笔记本上网,Ad hoc无线连网应用
    【openfire插件开发】群组聊天中的中介者模式
  • 原文地址:https://www.cnblogs.com/jkwll/p/11884171.html
Copyright © 2020-2023  润新知