stringbuffer在单线程中仍因synchronized锁机制产生monitor操作、内存屏障及粗粒度同步等开销,而stringbuilder无锁,性能更高。

因为 synchronized 锁会引入实际的线程调度开销和内存同步成本,哪怕只在单线程中调用 StringBuffer,JVM 仍要走完整的锁机制流程。
锁本身就有执行成本
synchronized 不是“没开销的开关”,它在 JVM 层涉及:
- 锁对象的监视器(monitor)获取与释放
- 可能触发偏向锁撤销、轻量级锁膨胀为重量级锁
- 每次进入/退出同步块都要插入内存屏障(memory barrier),保证可见性
- 即使没有竞争,这些逻辑也照常执行,无法跳过
方法粒度粗,同步范围大
StringBuffer 几乎所有 public 方法(append、insert、delete、reverse、toString 等)都加了 synchronized —— 这意味着:
- 一次 append 调用就要独占整个对象,其他线程哪怕想读 length 或调用另一个不冲突的操作,也得排队
- 无法做细粒度控制,比如只锁内部 char[] 的写入段,而是锁住整个实例
- 连续调用多个方法(如 sb.append("a").append("b").append("c"))会反复进出锁,放大开销
toString 操作也有额外负担
StringBuffer 的 toString() 会尝试复用内部缓存(toStringCache),但这个缓存本身也要被同步保护;而 StringBuilder 每次 toString 都直接复制数组——看似多一次复制,实则省去了锁检查+缓存一致性维护的综合成本。在高频拼接+频繁转字符串的场景下,这个差异会累积显现。
对比 StringBuilder 就更明显
StringBuilder 完全绕开了锁机制:
- 方法调用就是普通 invokevirtual,无 monitor 指令
- 底层复用 AbstractStringBuilder 的 char[],扩容逻辑一致,仅差在同步层
- 实测在单线程下,StringBuilder 通常比 StringBuffer 快 10%–15%,高并发无竞争时差距可能达 5 倍
不是 synchronized 写得不好,而是它为多线程安全付出的代价,在单线程或低竞争场景下显得“重”了。











