当前位置: 首页 > article >正文

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 + synchronizedLock适用于单线程,性能更好

💡 如何选择?

  • 单线程:使用 StringBuilder,性能更高
  • 多线程:使用 StringBuffer,防止数据竞争
  • 多线程但性能要求高?可以使用 StringBuilder + synchronizedLock

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 进行手动控制

💡 面试高频考点

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

相关文章:

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

1. 什么是线程安全 & 线程不安全&#xff1f; 线程安全&#xff08;Thread-Safe&#xff09;&#xff1a;在多线程环境下访问同一个对象时&#xff0c;不会产生数据竞争、不会出现数据不一致的问题。线程不安全&#xff08;Not Thread-Safe&#xff09;&#xff1a;在多线…...

rem、em、vw区别

在前端开发里&#xff0c;rem、em、vw都是用来设置元素大小的单位&#xff0c;下面就用大白话讲讲它们的区别。 参考标准不一样 rem&#xff1a;就像大家都用同一把“大尺子”来量东西&#xff0c;这把“大尺子”就是网页里根元素&#xff08;也就是 <html> 标签&#…...

【PHP】php+mysql 活动信息管理系统(源码+论文+数据库+数据库文件)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 【PHP】php 活动信息管理系统&#xff08;源码论文…...

cURL请求与Javascript请求转换工具

cURL请求与Javascript请求在线转换工具(如 curlconverter) 首先,看看各个证据中关于curl的定义。提到cURL是“Client for URLs”的缩写,最初全大写是为了方便记忆,社区也将其解释为“Client URL Request Library”或递归的“Curl URL Request Library”。同时,还指出cURL…...

rv1103b编译opencv

opencv-3.4.16&#xff0c;png的neon会报错&#xff0c;如果想开可以参考 https://blog.csdn.net/m0_60827485/article/details/137561429 rm -rf build mkdir build cd build cmake -DCMAKE_BUILD_TYPERELEASE \ -DCMAKE_C_COMPILERxxx/arm-rockchip831-linux-uclibcgnueabih…...

thingboard告警信息格式美化

原始报警json内容&#xff1a; { "severity": "CRITICAL","acknowledged": false,"cleared": false,"assigneeId": null,"startTs": 1739801102349,"endTs": 1739801102349,"ackTs": 0,&quo…...

OpenHarmonry 5.0.1源码下载与编译

预置环境&#xff1a;硬盘500G、内存32G、Ubuntu 20.04.6 LTS Ubuntu系统下载路径&#xff1a;ubuntu-releases安装包下载_开源镜像站-阿里云 一、必需环境 sudo apt-get update && sudo apt-get install binutils binutils-dev git git-lfs gnupg flex bison gperf…...

【Python深入浅出㊸】解锁Python3中的TensorFlow:开启深度学习之旅

目录 一、TensorFlow 简介1.1 定义与背景1.2 特点 二、Python 3 与 TensorFlow 的关系2.1 版本对应2.2 为何选择 Python 3 三、安装 TensorFlow3.1 安装步骤3.2 验证安装 四、TensorFlow 基本概念与使用方法4.1 计算图&#xff08;Graph&#xff09;4.2 会话&#xff08;Sessio…...

STM32 外部中断和NVIC嵌套中断向量控制器

目录 背景 外部中断/事件控制器(EXTI) 主要特性 功能说明 外部中断线 嵌套向量中断控制器 特性 ‌中断线&#xff08;Interrupt Line&#xff09; 中断线的定义和作用 STM32中断线的分类和数量 优先级分组 抢占优先级&#xff08;Preemption Priority&#xff09; …...

string类详解(上)

文章目录 目录1. STL简介1.1 什么是STL1.2 STL的版本1.3 STL的六大组件 2. 为什么学习string类3. 标准库中的string类3.1 string类3.2 string类的常用接口说明 目录 STL简介为什么学习string类标准库中的string类string类的模拟实现现代版写法的String类写时拷贝 1. STL简介 …...

DeepSeek教unity------Dotween

1、命名法 Tweener&#xff08;补间器&#xff09;&#xff1a;一种控制某个值并对其进行动画处理的补间。 Sequence&#xff08;序列&#xff09;&#xff1a;一种特殊的补间&#xff0c;它不直接控制某个值&#xff0c;而是控制其他补间并将它们作为一个组进行动画处理。 Tw…...

AIP-146 泛化域

编号146原文链接AIP-146: Generic fields状态批准创建日期2019-05-28更新日期2019-05-28 API中的大多数域&#xff0c;无论是在请求、资源还是自定义应答中&#xff0c;都有具体的类型或模式。这个模式是约定的一部分&#xff0c;开发者依此约定进行编码。 然而&#xff0c;偶…...

【Go并发编程】Goroutine 调度器揭秘:从 GMP 模型到 Work Stealing 算法

每天一篇Go语言干货&#xff0c;从核心到百万并发实战&#xff0c;快来关注魔法小匠&#xff0c;一起探索Go语言的无限可能&#xff01; 在 Go 语言中&#xff0c;Goroutine 是一种轻量级的并发执行单元&#xff0c;它使得并发编程变得简单高效。而 Goroutine 的高效调度机制是…...

【前端】Vue组件库之Element: 一个现代化的 UI 组件库

文章目录 前言一、官网1、官网主页2、设计原则3、导航4、组件 二、核心功能&#xff1a;开箱即用的组件生态1、丰富的组件体系2、特色功能亮点 三、快速上手&#xff1a;三步开启组件化开发1、安装&#xff08;使用Vue 3&#xff09;2、全局引入3、按需导入&#xff08;推荐&am…...

第十五天 学习并实践HarmonyOS应用的基本结构、页面导航和状态管理

HarmonyOS应用开发入门&#xff1a;从基本结构到状态管理实战指南 前言 &#xff08;约300字&#xff0c;说明HarmonyOS的发展前景&#xff0c;应用开发的市场需求&#xff0c;以及本教程的核心价值。强调手把手教学特点&#xff0c;降低学习门槛&#xff09; 一、HarmonyOS应…...

Cursor生成JAVA相关的关键词提示规则

在项目根目录创建一个.curstorrules文件&#xff08;注意有个小数点&#xff09;&#xff0c;之后在该文件内填入下面内容 你是 Java 编程、Spring Boot、Spring Framework、Maven、JUnit 及相关 Java 技术的专家。 代码风格与结构 编写整洁、高效且文档完善的 Java 代码&am…...

数据结构:队列(Queue)及其实现

队列&#xff08;Queue&#xff09;是一种广泛使用的线性数据结构&#xff0c;它遵循先进先出&#xff08;FIFO&#xff0c;First In, First Out&#xff09;的原则。也就是说&#xff0c;最早插入队列的元素会最先被移除。队列是一种典型的顺序存取结构&#xff0c;它与栈&…...

MoE架构中的专家选择门控机制:稀疏激活如何实现百倍效率突破?

技术原理&#xff08;数学公式与核心逻辑&#xff09; 核心公式 门控网络输出&#xff1a; G ( x ) Softmax ( W g ⋅ x b g ) G(x) \text{Softmax}(W_g \cdot x b_g) G(x)Softmax(Wg​⋅xbg​) 最终输出&#xff1a; y ∑ i 1 n G i ( x ) ⋅ E i ( x ) (仅保留Top-…...

坐井说天阔---DeepSeek-R1

前言 DeepSeek-R1这么火&#xff0c;虽然网上很多介绍和解读&#xff0c;但听人家的总不如自己去看看原论文。于是花了大概一周的时间&#xff0c;下班后有进入了研究生的状态---读论文。 DeepSeek这次的目标是探索在没有任何监督数据的情况下训练具有推理能力的大模型&#…...

UART(一)——UART基础

一、定义 UART(Universal Asynchronous Receiver/Transmitter)是一种广泛使用的串行通信协议,用于在设备间通过异步方式传输数据。它无需共享时钟信号,而是依赖双方预先约定的参数(如波特率)完成通信。 功能和特点 基本的 UART 系统只需三个信号即可提供稳健的中速全双工…...

DeepSeek 的创新融合:多行业应用实践探索

引言 在数字化转型的浪潮中&#xff0c;技术的融合与创新成为推动各行业发展的关键力量。蓝耘平台作为行业内备受瞩目的创新平台&#xff0c;以其强大的资源整合能力和灵活的架构&#xff0c;为企业提供了高效的服务支持。而 DeepSeek 凭借先进的人工智能技术&#xff0c;在自然…...

C语言中的常量与只读变量,#define与const的区别

#include中的#表明C处理器需要在编译器接手工作之前先处理这条指令。 #define 这条定义宏的语句&#xff0c;是不是很熟悉&#xff0c;这条预处理指令会在编译器编译前把源文件中使用到这个宏的地方都先展开。 #define NUM 12 这个定义了一个宏常量&#xff0c;它的处理发生编…...

Python常见面试题的详解6

1. 按字典 value 值排序 要点&#xff1a;对于给定字典&#xff0c;使用 sorted() 函数结合 items() 方法&#xff0c;依据 value 进行排序&#xff0c;也可以定义一个通用函数&#xff0c;支持按 value 升序或降序排序。示例&#xff1a; python d {a: 1, b: 2, c: 3, d: …...

CentOS 7超详细安装教程(含镜像)

1. 安装前准备 1.1 CentOS简介 CentOS&#xff08;Community Enterprise Operating System&#xff0c;中文意思是&#xff1a;社区企业操作系统&#xff09;是一种基于 Red Hat Enterprise Linux&#xff08;RHEL&#xff09;源代码构建的免费开源操作系统。它在稳定性、安全…...

代码随想录day12

144.二叉树的前序遍历 //明确递归的函数&#xff0c;结束边界&#xff0c;单层逻辑 void traversal(TreeNode* node, vector<int>& list){if(node nullptr){return;}list.push_back(node->val);traversal(node->left, list);traversal(node->right, list)…...

langchain学习笔记之消息存储在内存中的实现方法

langchain学习笔记之消息存储在内存中的实现方法 引言背景消息存储在内存的实现方法消息完整存储&#xff1a;完整代码 引言 本节将介绍 langchain \text{langchain} langchain将历史消息存储在内存中的实现方法。 背景 在与大模型交互过程中&#xff0c;经常出现消息管理方…...

布隆过滤器(简单介绍)

布隆过滤器&#xff08;Bloom Filter&#xff09; 是一种高效的概率型数据结构&#xff0c;用于快速判断一个元素是否可能存在于某个集合中。它的核心特点是空间效率极高&#xff0c;但存在一定的误判率&#xff08;可能误报存在&#xff0c;但不会漏报&#xff09;。 核心原理…...

Qt中基于开源库QRencode生成二维码(附工程源码链接)

目录 1.QRencode简介 2.编译qrencode 3.在Qt中直接使用QRencode源码 3.1.添加源码 3.2.用字符串生成二维码 3.3.用二进制数据生成二维码 3.4.界面设计 3.5.效果展示 4.注意事项 5.源码下载 1.QRencode简介 QRencode是一个开源的库&#xff0c;专门用于生成二维码&…...

SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪

SpringBoot教程&#xff08;三十二&#xff09; | SpringBoot集成Skywalking链路跟踪 一、Skywalking是什么&#xff1f;二、Skywalking与JDK版本的对应关系三、Skywalking下载四、Skywalking 数据存储五、Skywalking 的启动六、部署探针 前提&#xff1a; Agents 8.9.0 放入 …...

IntelliJ IDEA 接入 AI 编程助手(Copilot、DeepSeek、GPT-4o Mini)

IntelliJ IDEA 接入 AI 编程助手&#xff08;Copilot、DeepSeek、GPT-4o Mini&#xff09; &#x1f4ca; 引言 近年来&#xff0c;AI 编程助手已成为开发者的高效工具&#xff0c;它们可以加速代码编写、优化代码结构&#xff0c;并提供智能提示。本文介绍如何在 IntelliJ I…...