StringBuffer线程安全的核心原因是其关键方法均用synchronized修饰,保证同一时刻仅一个线程执行实例的同步方法,但多方法组合调用仍需手动加锁以防竞态。

Java 中 StringBuffer 是线程安全的,核心原因在于它的关键方法(如 append、insert、delete、reverse 等)内部都使用了 synchronized 关键字进行同步控制。
StringBuffer 的 synchronized 方法如何工作
StringBuffer 的大多数公共修改方法都被声明为 synchronized,这意味着:
- 每个方法调用都会获取当前 StringBuffer 实例的对象锁;
- 同一时刻只有一个线程能执行该实例上的任意一个 synchronized 方法;
- 其他线程若尝试调用该实例的 synchronized 方法,会被阻塞,直到锁被释放。
例如:
public synchronized StringBuffer append(String str) { ... }
这种设计保证了多线程环境下对同一 StringBuffer 对象的并发操作不会导致数据错乱(比如字符数组越界、长度不一致、内容覆盖等)。
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
线程安全的边界仅限于单个方法调用
虽然每个方法是同步的,但多个方法的组合调用并不自动线程安全。例如:
sb.length(); // 读取长度
sb.append("x"); // 再追加
这两行代码之间可能有其他线程修改了 sb,导致“检查后使用”(check-then-act)竞态条件。此时需手动加锁:
synchronized(sb) {
if (sb.length() }
与 StringBuilder 的关键区别
StringBuilder 提供了和 StringBuffer 完全相同的 API,但所有方法均未加 synchronized。因此:
- StringBuilder 性能更高(无同步开销),适合单线程场景;
- StringBuffer 虽慢一些,但在需要共享可变字符串且无法避免多线程访问时,是更稳妥的选择;
- 若需在多线程中高性能拼接,应考虑使用 ThreadLocal<stringbuilder></stringbuilder> 或并行流 + 不可变字符串组合方式,而非全局共享 StringBuffer。
实际使用中的注意事项
– 不要误以为“用了 StringBuffer 就万事大吉”,仍需注意复合逻辑的同步;
– 在高并发写入场景下,StringBuffer 的串行化会成为瓶颈,应评估是否真需共享可变状态;
– Java 9+ 中底层字符存储已从 char[] 改为 byte[](支持紧凑字符串),但 synchronized 语义和线程安全性保持不变;
– 若仅需线程安全的只读字符串构建,优先考虑不可变对象(如用 String.join() 或 Collectors.joining())。

















