• 为什么说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的时候,在内存中就不同步啦

  • 相关阅读:
    proxmox新版本使用了lxc容器,导致以前的vzlist命令无法使用,于是自己写了一个脚本来获取所有半虚拟化主机的信息状态
    Linux 系统优化参数总结
    linux shell 远程执行命令
    wios设置证书登陆
    Eclipse安装tomcat插件
    Centos6.5-dnsmasq安装
    SSL工作原理
    ssh免密码登陆及其原理
    Linux查看后台任务,关闭后台任务
    Mybatis 中常用的java类型与jdbc类型
  • 原文地址:https://www.cnblogs.com/jkwll/p/11884171.html
Copyright © 2020-2023  润新知