stringbuffer 天生线程安全,靠的是所有公共修改方法(如 append、insert)均被声明为 public synchronized,通过 this 锁实现串行化访问,确保多线程共用时不会出现数据错乱或异常。

StringBuffer 在多线程环境下能安全拼接字符串,靠的是方法级的 synchronized 同步机制——每个公共修改方法(如 append、insert、delete)都自带内置锁,确保同一时刻只有一个线程能执行该操作。
StringBuffer 为什么天生线程安全
它不是靠“避免共享”,而是靠“串行化访问”:所有可能改变内部状态的方法都被声明为 public synchronized。这意味着调用时会自动获取当前 StringBuffer 实例的对象锁(this 锁),其他线程若想调用同步方法,必须等待锁释放。
- 内部字符数组(
value)虽可变,但所有读写操作都受锁保护,不会出现中间态被并发读取或覆盖 - 即使多个线程共用同一个 StringBuffer 实例,
append("a")和append("b")也不会交错成乱序或丢数据 - 注意:只对 StringBuffer 对象本身的操作是线程安全的;若在同步块外手动修改其内部字段(如反射绕过),仍可能破坏安全性
多线程拼接的典型写法
直接复用一个 StringBuffer 实例,在多个线程中调用 append() 即可,无需额外加锁或包装:
- 定义共享实例(如 static 或通过依赖注入传递)
- 各线程独立调用
sb.append("xxx"),顺序由锁自动保障 - 全部线程结束后,调用
sb.toString()获取最终结果
示例关键片段:
static StringBuffer sb = new StringBuffer();// 线程1:
sb.append("Hello");
// 线程2:
sb.append("World");
// 最终结果一定是 "HelloWorld" 或 "WorldHello"(取决于执行顺序),但绝不会是字符错位或抛出异常
和 StringBuilder 的关键区别
StringBuilder 所有方法都没有 synchronized,因此在多线程下直接共用会引发竞态条件——比如两个线程同时执行 append(),可能因共享的 count 和 value 数组更新不同步,导致长度错乱、数组越界或内容丢失。
- 单线程场景优先用 StringBuilder:快,无锁开销
- 明确需要多线程共享拼接时,选 StringBuffer:安全,语义清晰
- 不建议用 synchronized 包裹 StringBuilder 来“模拟”线程安全——既没解决内部状态竞争,又失去性能优势
实际使用注意事项
线程安全 ≠ 使用无误。以下情况仍需小心:
- 如果拼接逻辑涉及条件判断、多次 append + 中间 toString(),且结果被其他线程依赖,需确认业务逻辑是否隐含时序要求
- StringBuffer 的同步粒度是方法级,不是整个拼接流程;若需原子性地完成一组操作(如“先清空再拼接”),应显式用
synchronized(sb) { ... } - 高并发下大量线程争抢同一 StringBuffer 锁,会造成明显阻塞,此时可考虑分段拼接 + 合并,或改用无锁方案(如
ThreadLocal<stringbuffer></stringbuffer>)











