stringbuffer 通过方法级 synchronized 锁保障多线程写操作完整性,每次调用 append、insert 等修改方法时独占实例锁,确保 value 数组和 count 计数器的原子性;但仅限单方法调用,跨方法组合需显式同步。

Java 中 StringBuffer 在多线程写操作中保证完整性,核心靠的是方法级 synchronized 锁——每次调用 append、insert、delete 等修改方法时,都独占该实例的对象锁(this),确保对内部字符数组(char[] value)和长度计数器(int count)的读写是原子的、互斥的。
单个方法调用天然原子
StringBuffer 所有公开修改方法(如 append("abc")、delete(0, 2))都被声明为 public synchronized。这意味着:
- 线程 A 调用
sb.append("x")时,会获取sb实例锁,完成整个追加逻辑(更新count、拷贝字符、必要时扩容)后才释放锁 - 线程 B 在此期间尝试调用任何同步方法(包括
length()或另一个append())都会被阻塞,无法干扰 A 的操作 - 不会出现字符覆盖、数组越界、
count错乱等底层数据不一致问题——内容完整性得到保障
完整性 ≠ 业务逻辑一致性
方法级同步只保护单次调用,不延伸到跨方法组合操作。例如以下代码无法保证结果符合预期:
错误示例:
if (sb.length() sb.append("data");<br>}
因为 length() 和 append() 是两次独立加锁操作,中间可能被其他线程插入修改。此时需显式同步:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
正确做法:
synchronized (sb) {<br> if (sb.length() sb.append("data");<br> }<br>}
真正需要 StringBuffer 的场景
它只在满足以下两个条件时才发挥不可替代的作用:
- 多个线程**共享同一个 StringBuffer 实例**(如作为 static 字段、或被多个 Runnable 共同引用)
- 这些线程**并发读写该实例**(不只是各自创建后丢弃)
典型例子:全局日志缓冲区、配置聚合器、响应体拼接池。若每个线程都新建 StringBuffer,则应改用 StringBuilder——无锁更快,且无共享即无竞争。
性能代价与实用建议
每次同步都有锁开销,在高并发写入下吞吐量明显下降。实际使用中建议:
- 初始化时指定合理容量(如
new StringBuffer(1024)),减少扩容时的锁争抢 - 避免嵌套同步(如方法已同步,再在外层加
synchronized(sb)),徒增开销 - 优先考虑更优替代:用
ThreadLocal<stringbuilder></stringbuilder>实现零锁复用;或让各线程生成字符串片段,最后由单线程合并
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










