StringBuffer 是线程安全的,因其所有公开方法均被 synchronized 修饰,通过对象级锁确保同一时刻仅一个线程执行操作,从而保障状态一致性;但复合操作非原子,需额外同步,且高并发下性能受限。

StringBuffer 通过内置同步机制避免多线程冲突。它的所有公开方法(如 append()、insert()、delete())都被 synchronized 修饰,保证同一时刻只有一个线程能执行这些操作,从而确保内部字符数组和长度等状态的一致性。
为什么 StringBuffer 是线程安全的
StringBuffer 的每个可变操作都加了对象级锁(即锁住当前 StringBuffer 实例),例如:
public synchronized StringBuffer append(String str)public synchronized char charAt(int index)
这意味着多个线程调用同一个 StringBuffer 对象的方法时,会串行执行,不会出现数据错乱(比如部分追加、索引越界或长度不一致等问题)。
实际使用中的注意事项
线程安全不等于“完全无风险”,仍需注意以下几点:
立即学习“Java免费学习笔记(深入)”;
- 复合操作(如先判断再修改)不是原子的,需额外同步。例如:
if (sb.length() == 0) sb.append("hello");这两步之间可能被其他线程打断。 - 如果 StringBuffer 被多个线程共享且频繁修改,性能会下降——同步带来开销,尤其在高并发场景下。
- 只读操作(如
toString()、length())虽也同步,但通常影响较小;真正瓶颈常出现在频繁append()或replace()的场景。
替代方案与取舍建议
根据场景选择更合适的工具:
- 单线程或局部变量:优先用
StringBuilder,性能更好,无需同步开销。 - 多线程且需共享可变字符串:StringBuffer 仍是合理选择,尤其兼容老代码或要求强一致性时。
- 高并发、复杂拼接逻辑:考虑用不可变对象(如 String + Stream)、线程本地变量(
ThreadLocal<stringbuffer></stringbuffer>),或更高层的并发集合/工具类。
不复杂但容易忽略:线程安全是 StringBuffer 的设计目标,但开发者仍要对操作语义保持清醒——同步只保方法级原子性,不保业务逻辑原子性。


















