stringbuffer线程安全而stringbuilder不安全:前者方法均加synchronized,后者无锁;多线程下stringbuffer保证数据一致,stringbuilder易出错;单线程中stringbuilder快5–15倍;stringbuffer有tostring缓存机制,stringbuilder没有。

核心区别就一条:StringBuffer 是线程安全的,StringBuilder 不是。
看方法有没有 synchronized
最直接的判断方式是查源码或 IDE 跳转——看 append()、insert()、delete() 这些公共方法的声明。
- StringBuffer 的每个 public 方法都带 synchronized 修饰符,比如
public synchronized StringBuffer append(String str) - StringBuilder 所有对应方法都不加 synchronized,比如
public StringBuilder append(String str)
这个规则覆盖全部公开 API,没有例外。
多线程改同一个对象会怎样
这是最真实的检验场景。
- 两个线程同时对同一个 StringBuffer 实例反复调用
append("x")各 10000 次,结果一定是 20000 个 x,数据始终一致 - 换成 StringBuilder,大概率少于 20000 个 x;还可能抛
ArrayIndexOutOfBoundsException,或出现字符乱序、内容截断等不可预测行为
原因在于:StringBuffer 用锁强制串行执行;StringBuilder 没锁,多个线程可能同时读 count、算下标、写 char 数组,导致一次写被另一次覆盖。
单线程下性能差多少
差距非常显著——StringBuilder 通常比 StringBuffer 快 5–15 倍。
- 同步锁的获取/释放、内存屏障、上下文切换等开销,在单线程里纯属冗余
- Web 请求中作为局部变量使用时,选 StringBuilder 不仅正确,而且必要
- 反过来,若误把 StringBuilder 当 StringBuffer 用在 Servlet 的成员变量上,就是典型的并发隐患
toString() 缓存机制也透露设计意图
StringBuffer 内部有 toStringCache 字段,每次修改前设为 null,toString 时先查缓存再决定是否复制数组;StringBuilder 根本没有这个字段。
- 这个细节说明 StringBuffer 在意“多次 toString”时的效率权衡,愿意多占内存、多维护状态
- 但前提是必须保证多线程下调用 toString() 看到的是某次完整修改后的结果,而不是中间态
- 这种权衡本身,就是为线程安全服务的
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











