stringbuffer 通过 synchronized 方法实现线程安全,所有公共操作互斥执行,锁住实例本身;扩容过程受同步保护,确保状态一致;但组合操作需外部同步;与 stringbuilder 的核心区别在于后者无同步,仅适用于单线程。

StringBuffer 本身通过内置同步机制协调多线程访问,无需额外加锁,就能保证对同一实例的并发修改是线程安全的。
所有公共方法都加了 synchronized
StringBuffer 的关键操作(如 append()、insert()、delete()、reverse() 等)全部被声明为 synchronized。这意味着每次只有一个线程能执行这些方法,其他线程必须等待当前线程释放对象锁后才能进入。
- 锁的是 StringBuffer 实例本身(即
this),不是类或静态资源 - 即使多个线程调用不同方法(比如一个在
append(),另一个在delete()),也会互斥执行 - 这种粒度确保了内部字符数组(
value)和长度(count)等字段不会出现读写冲突或数据错乱
扩容时的线程安全性也受保护
当字符串内容超出当前容量时,StringBuffer 会自动扩容(通常复制到新数组)。这个过程涉及创建新数组、拷贝旧内容、更新 value 引用和 count 值——整套操作被包裹在同步块内。
- 不会出现“部分拷贝”导致的脏读或数组越界
- 其他线程看到的始终是完整、一致的状态:要么是旧数组且
count正确,要么是新数组且已完全初始化
注意:仅方法调用原子,组合操作仍需外部同步
单个方法调用是线程安全的,但多个方法连用(如先 length() 再 charAt())不构成原子操作。
- 例如:
if (sb.length() > 0) sb.charAt(0);可能因中间被其他线程清空而抛出StringIndexOutOfBoundsException - 若需逻辑上的原子性(比如“检查+修改”),应手动用
synchronized(sb) { ... }包裹整个代码块 - 这是设计使然,并非缺陷——StringBuffer 提供的是方法级安全,而非业务逻辑级安全
与 StringBuilder 的关键区别
StringBuilder 功能几乎完全相同,但所有方法都不加 synchronized。它适合单线程场景,性能更高;而 StringBuffer 明确为多线程设计,牺牲一点性能换取开箱即用的安全性。
- 不要因为“StringBuffer 慢”就盲目替换为 StringBuilder,除非确认无并发访问
- 若已有 StringBuffer 被多线程共享,直接换成 StringBuilder 会导致数据竞争,行为不可预测
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











