StringBuffer 的同步机制基于实例级 synchronized 方法,锁对象为 this,确保单个方法原子性但不保证复合操作安全,非同步读方法可并发执行,与 StringBuilder 的区别仅在于是否内置同步。

StringBuffer 的同步机制靠的是每个修改方法自带 synchronized 修饰符,锁对象是实例自身(this),不是额外加锁,也不是类级别锁。
所有关键方法都加了 synchronized
比如 append()、insert()、delete()、reverse()、setCharAt() 等公开修改方法,源码里都明确声明为 public synchronized。调用时线程必须先获取该 StringBuffer 实例的对象锁,执行完自动释放,无需手动干预。
- 底层字节码带
ACC_SYNCHRONIZED标志,由 JVM 直接支持 - 锁粒度是实例级——不同 StringBuffer 对象之间互不干扰
- 非同步方法如 length()、charAt()、capacity() 可并发读取,不参与锁竞争
同步只保单个方法的原子性
一个 append() 是安全的,但两步操作组合就不行。比如先判断长度再追加,中间可能被其他线程改掉内容。
- 典型风险:“检查后使用”(check-then-act),如
if (sb.length() - 读-改-写序列,如
int len = sb.length(); sb.delete(0, len/2),len 可能已失效 - 这类逻辑必须用显式同步块包裹:
synchronized(sb) { ... }
为什么不用 static 同步或外部锁
用 this 锁 是为了最小化锁范围:只在真正共享同一个 StringBuffer 实例时才排队,避免全局串行化。
立即学习“Java免费学习笔记(深入)”;
- 两个独立实例
sb1和sb2可被不同线程同时操作 - 符合“保护共享状态”的设计原则,兼顾安全与并发效率
- 如果用类锁,所有 StringBuffer 都会互相阻塞,完全没必要
和 StringBuilder 的本质区别
两者 API 完全一样,差异仅在于并发控制策略:
- StringBuffer:方法加 synchronized,适合多线程反复读写同一实例
- StringBuilder:无任何同步,单线程下性能高约 80%–100%
- toString() 返回新 String 对象,不受 StringBuffer 锁保护,后续操作与原对象无关


















