StringBuilder线程不安全,因其append等操作非原子,涉及读count、写value数组、更新count三步,且无synchronized或volatile保护,多线程并发时会导致丢失修改、ArrayIndexOutOfBoundsException等异常。

面试官考 StringBuilder 的线程安全性,不是只问“它是否线程安全”,而是层层递进,重点看你能否讲清“为什么 unsafe”、在什么场景下真会出问题、以及如何规避——光背结论容易被反杀。
一、常考提问方式(不直接问定义)
这类题很少直给“StringBuilder 和 StringBuffer 有什么区别”。真实考法更隐蔽:
- “你平时拼接字符串用哪个?为什么不用 StringBuffer?”
- “如果把 StringBuilder 声明为 static 成员变量,多线程调用它的 append 方法,会发生什么?”
- “下面这段代码有没有线程安全问题?为什么?”(附含局部变量/参数传递/共享引用的代码片段)
- “既然 StringBuilder 不安全,那为什么 JDK 还保留它?有没有比 StringBuffer 更优的多线程替代方案?”
二、必须答准的底层原因
不能只说“没加 synchronized”。要指出具体机制缺陷:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 内部 char[] 数组可被多个线程同时读写,append() 等操作包含“读当前长度→写入新字符→更新长度”三步,非原子操作
- 扩容时涉及数组复制和引用替换,若两个线程同时触发扩容,可能一个线程覆盖另一个的副本,导致数据丢失或越界异常
- 所有方法(append、insert、delete、reverse)均无同步控制,也没有 volatile 修饰关键字段(如 count),无法保证可见性
三、关键场景辨析(高频陷阱点)
面试官最爱拿“看似安全,实则危险”的例子卡人:
立即学习“Java免费学习笔记(深入)”;
- 局部变量创建 → 安全:每个线程在自己栈帧里 new StringBuilder,互不影响
- 作为参数传入 → 危险:若调用方传的是同一个实例,被多个线程并发修改,就会错乱
- 静态变量或单例持有 → 极危险:所有线程共享同一对象,典型竞态条件
- 方法返回 StringBuilder 引用 → 危险:调用方拿到后可能被其他线程继续修改
四、高分回答加分项
答到这层,基本能拉开差距:
- 指出 JDK 后续优化思路:比如用 ThreadLocal 隔离线程,兼顾性能与安全
- 提到现代替代方案:StringJoiner(适合固定分隔符拼接)、String.format(轻量格式化)、甚至直接用 List + Collectors.joining(函数式风格)
- 补充实际经验:线上曾因 static StringBuilder 被多线程共用,导致日志内容错位、JSON 字段缺失等隐蔽问题

















