stringbuffer线程安全因其所有公开修改方法均用synchronized修饰,锁对象为实例本身,确保同一实例多线程调用append、insert等操作串行执行;但仅保障单方法原子性,多步组合需手动同步,单线程场景应优先选用性能更高的stringbuilder。

StringBuffer 是 Java 中专为多线程文本操作设计的可变字符串类,它的线程安全性不是靠外部加锁实现的,而是由每个公开方法自带 synchronized 保证——这意味着只要用的是同一个 StringBuffer 实例,多个线程调用 append、insert、delete 等操作天然不会互相干扰,无需额外同步代码。
为什么 StringBuffer 能在线程间安全共享?
关键在于所有修改方法(如 append、insert、replace、reverse)都声明为 public synchronized,锁对象是该 StringBuffer 实例本身(this)。当线程 A 进入 append(),它就持有了该实例的监视器锁;此时线程 B 若尝试调用同一实例的 insert(),会被阻塞,直到 A 执行完并释放锁。这种串行化执行确保了字符数组(char[] value)的状态始终一致,避免了数据错乱或数组越界等并发问题。
实际开发中怎么用才真正安全?
- 必须确保多个线程操作的是同一个 StringBuffer 实例,而不是各自 new 出来的副本。若每个线程都创建自己的 StringBuffer,那“线程安全”毫无意义
- 不要在 synchronized 方法内部再手动加锁(比如对 this 再 synchronized),会造成死锁风险
- 避免将 StringBuffer 作为静态全局变量随意暴露给不可控线程——虽然它本身安全,但业务逻辑可能仍需更高层的协调(例如追加日志后统一 flush)
- 注意 toString() 返回的是新 String 对象,不改变原 StringBuffer,但频繁调用会触发内部缓存(toStringCache)重建,不影响线程安全,但有轻微性能波动
什么时候不该用 StringBuffer?
单线程场景下,优先选 StringBuilder:它和 StringBuffer 底层结构完全一样(都继承 AbstractStringBuilder,共用 char[] 和扩容逻辑),只是去掉了 synchronized。实测 JDK 17 下百万次 append,StringBuilder 比 StringBuffer 快约 80%。如果你的字符串拼接发生在 Controller 层、工具方法或循环内,且无共享状态,用 StringBuilder 更合理。
替代方案:需要更高灵活性怎么办?
如果业务既要线程安全,又要求细粒度控制(比如只对某段操作加锁,或配合其他资源同步),可以考虑:
- 用 StringBuilder + 外部 ReentrantLock 或 synchronized 块,按需锁定关键区段
- 用 ThreadLocal
,为每个线程分配独立实例,彻底规避竞争——适合线程生命周期明确、不跨线程传递的场景(如 Web 请求处理) - 对高并发日志拼接等场景,可结合无锁队列(如 Disruptor)+ 不可变消息对象,把字符串构造推迟到消费端
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











