主页 > 人工智能  > 

20250214随笔线程安全线程不安全

20250214随笔线程安全线程不安全
1. 什么是线程安全 & 线程不安全? 线程安全(Thread-Safe):在多线程环境下访问同一个对象时,不会产生数据竞争、不会出现数据不一致的问题。线程不安全(Not Thread-Safe):在多线程环境下,多个线程同时访问同一个对象可能会导致数据不一致,需要手动加锁或者使用线程安全的方式来操作。
2. StringBuffer 线程安全,StringBuilder 线程不安全

💡 主要区别在于:

StringBuffer 是线程安全的,因为它的很多方法都加了 synchronized 关键字。StringBuilder 是线程不安全的,因为它没有加 synchronized,多线程访问时可能会出现数据不一致问题。 🔹 StringBuffer(线程安全) StringBuffer sb = new StringBuffer("Hello"); // 多线程修改同一个 StringBuffer 对象 Thread t1 = new Thread(() -> { sb.append(" World"); }); Thread t2 = new Thread(() -> { sb.append(" Java"); }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(sb); // 结果是可预测的,因为 append() 方法是同步的

🔹 StringBuffer 内部的方法(如 append()、insert())都加了 synchronized,保证了 同一时刻只有一个线程可以修改 StringBuffer 对象,所以它是 线程安全的。


🔹 StringBuilder(线程不安全) StringBuilder sb = new StringBuilder("Hello"); // 多线程修改 StringBuilder Thread t1 = new Thread(() -> { sb.append(" World"); }); Thread t2 = new Thread(() -> { sb.append(" Java"); }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(sb); // 可能输出 Hello World Java,也可能出现乱码

🔹 StringBuilder 没有 synchronized,多个线程同时访问时,可能会发生数据错乱,如:

Hello WorldJava Hello JavaWorld Hello WJavorld

💡 因为多个线程可以同时修改 StringBuilder,导致数据写入时发生竞争,出现不可预测的情况。


3. StringBuffer & StringBuilder 内部实现区别

📌 StringBuffer 使用 synchronized,保证线程安全

public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }

🔹 append() 方法使用了 synchronized,意味着同一时刻只有一个线程能执行它,这样就保证了线程安全。

📌 StringBuilder 没有 synchronized,线程不安全

public StringBuilder append(String str) { super.append(str); return this; }

🔹 append() 方法没有 synchronized,多个线程同时修改时会产生数据竞争。


4. 线程安全 vs 线程不安全,如何选择? 特性StringBuffer(线程安全)StringBuilder(线程不安全)是否线程安全✅ 是❌ 不是是否使用 synchronized✅ 是(同步)❌ 不是(无锁)适用场景多线程环境(如 Web 服务器、并发任务)单线程环境(普通字符串拼接)性能较慢(加锁有性能损耗)更快(无锁操作)替代方案StringBuilder + synchronized 或 Lock适用于单线程,性能更好

💡 如何选择?

单线程:使用 StringBuilder,性能更高。多线程:使用 StringBuffer,防止数据竞争。多线程但性能要求高?可以使用 StringBuilder + synchronized 或 Lock。
5. 线程安全一定好?为什么有线程不安全的 StringBuilder?

💡 线程安全的代价是“性能下降”:

StringBuffer 每次操作都需要 synchronized,即使单线程也会加锁,影响性能。StringBuilder 不加锁,在单线程下性能更快,适合大多数情况。

示例:StringBuffer 在单线程下的性能劣势

long startTime = System.nanoTime(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < 100000; i++) { sb.append("Java"); } long endTime = System.nanoTime(); System.out.println("StringBuffer 时间:" + (endTime - startTime) + " ns");

对比:StringBuilder 在单线程下的性能

long startTime = System.nanoTime(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100000; i++) { sb.append("Java"); } long endTime = System.nanoTime(); System.out.println("StringBuilder 时间:" + (endTime - startTime) + " ns");

💡 单线程下,StringBuilder 速度明显更快,因为它没有加锁!


6. 线程安全 & 线程不安全的选择策略 场景推荐选择单线程字符串拼接✅ StringBuilder多线程共享字符串对象✅ StringBuffer多线程 + 高性能要求✅ StringBuilder + synchronized不可变字符串(不修改)✅ String
7. 结论

✅ StringBuffer 是线程安全的,因为它的方法加了 synchronized,适用于多线程环境。 ✅ StringBuilder 是线程不安全的,但性能更好,适用于单线程环境。 ✅ 线程安全不一定好,StringBuffer 虽然安全,但单线程下性能比 StringBuilder 差。 ✅ 如果多线程但又想提升性能,可以使用 StringBuilder + synchronized 进行手动控制。

💡 面试高频考点:

StringBuffer 和 StringBuilder 的区别?为什么 StringBuilder 是线程不安全的?如何让 StringBuilder 变成线程安全的? ✅ 答案:加 synchronized,或者使用 Lock什么时候用 StringBuffer?什么时候用 StringBuilder? ✅ 单线程用 StringBuilder,多线程用 StringBuffer
标签:

20250214随笔线程安全线程不安全由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“20250214随笔线程安全线程不安全