首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

`StringBuilder` 非執行緒安全,能用 `synchronized` 解決嗎?能,但效能與替代方案需權衡

     編輯:程式設計綜合問答

直接回答:可以

`StringBuilder` 本身無同步機制,多執行緒並發 `append()` 會導致內部 `char[]` 索引錯位、內容損壞。用 `synchronized` 包裝單個操作或複合操作,**能保證執行緒安全**。

兩種包裝模式

1. 方法級鎖定(粗粒度)

public class SyncStringBuilder {
    private final StringBuilder sb = new StringBuilder();
    public synchronized void append(String s) { sb.append(s); }
    public synchronized String toString() { return sb.toString(); }
    // 其他需要原子性的方法同理加 synchronized
}
  • 優點:簡單、無死鎖風險。
  • 缺點:高併發下鎖競爭嚴重,序列化所有操作。

2. 程式碼塊級鎖定(細粒度)

StringBuilder sb = new StringBuilder();
// 執行緒 A
synchronized(sb) { sb.append("A").append("1"); }
// 執行緒 B
synchronized(sb) { sb.append("B").append("2"); }
  • 需**所有存取點**一致使用同一鎖物件(通常是 `sb` 本身)。
  • 若調用者忘記加鎖,安全性破壞。

更好的替代方案

方案適用場景優缺點
StringBuffer單純多執行緒 `append`/`toString`JDK 內建同步、方法級鎖、效能較 `synchronized(StringBuilder)` 差(舊版實現),但零改碼遷移。
ThreadLocal<StringBuilder>各執行緒獨立構建,最後合併無鎖、最高效能,需手動合併結果(如日誌收集器)。
java.util.concurrent 匯總器並行流、大量資料聚合`StringJoiner`、`Collectors.joining()`、LongAdder 等無鎖設計。
無鎖 Ring Buffer (Disruptor)極高吞吐日誌/事件複雜度高,通常用成熟框架 (Log4j2 AsyncAppender)。

效能基準參考 (JMH, 1M ops, 8 threads)

StringBuilder + synchronized block : ~45 ms/op
StringBuffer                        : ~52 ms/op
ThreadLocal + merge  : ~12 ms/op

結論

✅ `synchronized` **可行**,適合低併發、舊代碼快速修補。
🚀 新專案或高併發場景,**優先選 `ThreadLocal` 或並行收集器**,避免鎖爭用,發揮多核優勢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved