StringBuffer 的 append 操作具有原子性,因其方法声明含 synchronized 关键字,锁住当前实例对象(this),确保扩容、复制、更新 count 等步骤整体执行不被中断;但仅限单次调用,组合操作需额外同步。

Java 中 StringBuffer 的 append 操作能保证原子性,靠的是方法声明上的 synchronized 关键字——每次调用时自动获取该实例的对象锁(this),确保整个 append 过程不会被其他线程打断。
锁住的是当前实例,不是类或静态资源
StringBuffer 的 append 方法签名是:
public synchronized StringBuffer append(String str)
这个 synchronized 锁住的是调用它的那个 StringBuffer 对象本身,也就是 this。这意味着:
立即学习“Java免费学习笔记(深入)”;
- 两个不同 StringBuffer 实例(如
sb1和sb2)可被多个线程同时调用append,互不干扰 - 只有当多个线程操作同一个 StringBuffer 实例时,才会排队等待锁释放
- 锁的粒度是对象级,不是类级(没有用
static synchronized)
单次 append 内部操作全受锁保护
一次 append() 执行期间,JVM 会保证以下动作全部完成且不被穿插:
- 检查内部字符数组容量是否足够
- 必要时扩容(如
value = Arrays.copyOf(value, newCapacity)) - 把新内容逐个复制进
value[]数组 - 更新长度字段
count - 清空
toStringCache(避免缓存脏数据)
这些步骤作为一个整体,在持有锁的状态下执行,不会出现“只写了一半就切换线程”导致数组越界、长度错乱或内容覆盖的问题。
注意:原子性仅限单个方法调用
虽然 append() 自身是原子的,但和它组合使用的其他操作并不自动受保护。例如:
if (sb.length() —— <code>length()是非同步方法,判断和追加之间存在竞态窗口-
int len = sb.length(); sb.delete(0, len / 2);—— 第二步执行时,len可能已失效
这类多步逻辑必须手动加锁:synchronized(sb) { ... },把整段代码包进同一临界区。
性能代价明确,别误用
每次 append 都要竞争并获取对象锁,属于粗粒度同步:
- 单线程场景下,比 StringBuilder 慢约 50%–85%
- 高并发时,锁争用明显,无分段锁、CAS 等优化机制
- 如果只是局部变量、每个线程独占一个 StringBuffer,完全没必要用它
真正需要跨线程共享修改的场景才适合用 StringBuffer;否则优先选 StringBuilder 或配合 ThreadLocal 使用。


















