StringBuffer 通过 synchronized 方法实现线程安全,锁对象为 this,保障单次操作原子性但不保证组合逻辑,不同实例互不影响,仅在真正共享修改场景下适用。

Java 中 StringBuffer 在多线程下靠每个修改方法加 synchronized 关键字实现线程安全,锁对象是 this 实例本身,确保同一时刻只有一个线程能执行 append、insert、delete 等操作,从而避免共享 char[] 数组被并发写乱。
同步机制落在具体方法上
StringBuffer 继承自 AbstractStringBuilder,但所有会改变内部状态的公开方法都被声明为 synchronized:
public synchronized StringBuffer append(String str)public synchronized StringBuffer insert(int offset, String str)public synchronized void delete(int start, int end)public synchronized StringBuffer reverse()public synchronized String toString()
每次调用时,JVM 会检查该 StringBuffer 实例的 monitor 锁;若已被占用,当前线程阻塞等待。整个过程由 JVM 底层支持,无需手动写 synchronized 块。
只保单次操作原子性,不保组合逻辑
synchronized 方法保障的是单个调用的完整性,比如一次 append 不会中途被打断、不会出现数组越界或 count 错乱。但它不管多步操作之间的间隙:
立即学习“Java免费学习笔记(深入)”;
-
if (sb.length() < 10) sb.append("x"):length() 是非同步方法,append() 是同步方法,中间可能被其他线程插入内容 -
int len = sb.length(); sb.delete(0, len / 2):第二步执行时,len 可能已失效 - 需要这类“检查-再操作”逻辑时,必须用显式同步块包裹:
synchronized(sb) { ... }
锁是对象级的,不同实例互不影响
它用的是 this 锁,不是 static 锁,所以:
- 两个独立的 StringBuffer 对象(如 sb1 和 sb2)可被多个线程同时操作,完全不阻塞
- 只有多个线程操作同一个实例时,才会排队串行执行
- 这种设计既守住共享状态的安全边界,又不无谓限制并发
实际使用中别误用、别滥用
线程安全 ≠ 任何时候都该用 StringBuffer:
- 局部变量拼接、for 循环内构建字符串 → 用 StringBuilder,性能高 50%–100%
- 每个线程自己创建并使用一个 StringBuffer → 仍应换 StringBuilder 或 ThreadLocal<StringBuilder>
- 真正需要多线程共享并并发修改同一缓冲区(如日志聚合器、全局统计拼接)→ 才适合用 StringBuffer
- 高并发频繁写入场景下,单个 StringBuffer 容易成为瓶颈,可考虑分段缓冲或并发收集后合并


















