StringBuffer 的线程安全靠每个修改方法加 synchronized 锁住 this 实例,保障原子性、可见性与有序性;但多步操作需显式同步,仅共享并发读写时才需使用。

Java 中 StringBuffer 的线程安全,靠的是每个公开修改方法(如 append、insert、delete、reverse、toString)都声明为 public synchronized,锁对象是该实例自身(this),从而强制同一时刻只有一个线程能执行这些方法。
同步作用在方法级别,不是整个对象生命周期
每次调用一个 synchronized 方法时,JVM 会尝试获取该 StringBuffer 实例的监视器锁(monitor lock)。如果锁已被占用,当前线程阻塞等待;方法执行完毕(含异常退出)后自动释放锁。这意味着:
- 单次
append("abc")是原子操作:字符数组扩容、内容复制、长度更新全部被锁保护,不会出现越界或计数错乱 - 不同 StringBuffer 实例之间互不干扰:sb1 和 sb2 可被多个线程同时操作,因为锁是实例级而非类级
- 非同步方法(如
length()、charAt()、capacity())可并发读取,不参与锁竞争
它提供三重 JVM 内存模型保障
synchronized 不只是“排队”,还确保多线程间的数据一致性:
-
原子性:方法内所有操作不可被中断,比如
count++和数组写入作为一个整体完成 -
可见性:线程进入同步块前,强制从主内存读取最新值(如
value[]数组和count);退出时把修改刷回主内存,其他线程立即可见 - 有序性:禁止编译器和 CPU 对同步块内指令重排序,并建立 happens-before 关系,保证跨线程操作顺序可靠
单方法安全 ≠ 多步逻辑安全
方法本身同步,但多个方法组合调用仍可能出问题。典型竞态是“检查后执行”:
立即学习“Java免费学习笔记(深入)”;
- 错误写法:
if (sb.length() < 10) sb.append("x");——length()和append()是两个独立同步方法,中间可能被其他线程修改 sb - 正确做法:用显式同步块包裹整段逻辑:
synchronized (sb) { if (sb.length() < 10) sb.append("x"); } - 类似陷阱还包括:
sb.charAt(i)后再sb.setCharAt(i, 'x'),或清空后拼接等需多步协同的操作
什么时候才真正需要 StringBuffer
它不是为“有线程”而存在,而是为“共享 + 并发读写”设计:
- ✅ 必须用:多个线程共用同一个实例(如 static 字段、Spring 管理的 bean、Runnable 共享参数)且持续读写
- ❌ 不必用:每个线程 new 一个 StringBuffer 仅自己用 → 改用 StringBuilder,性能高 2–3 倍
- ⚠️ 更优替代:高并发场景下,优先考虑
ThreadLocal<StringBuilder>或分段收集 + 单线程合并,避免全局锁瓶颈


















