【Spring篇01】:Bean的线程安全问题总结

文章目录

  • 1. 核心问题:Spring 框架中的 Bean 是线程安全的吗?
  • 2. 最佳实践与解决方案
    • 禁止方案:滥用`prototype`作用域
    • 推荐方案(按优先级排序)
  • 3. 生产环境中的典型案例
    • Case 1:订单服务统计
    • Case 2:用户会话存储
  • 4. 关键总结

1. 核心问题:Spring 框架中的 Bean 是线程安全的吗?

核心点:

  • Spring 中的 Bean 默认是单例singleton)的。
  • 默认不线程安全: Spring 框架本身不对单例 Bean 进行线程安全封装。
  • 线程安全取决于使用方式: 如果 Bean 的状态是不可变的,或者不包含可变状态,则在某种程度上是线程安全的。如果 Bean 包含可变状态且多线程同时访问,就需要考虑线程安全问题。
  • 解决方案: 改变作用域(prototype,可多例)或自行处理线程同步。

让我们用一个通俗的类比来理解:

类比:一个公共图书馆的书籍

  • Spring 容器: 想象一下 Spring 容器是一个大型的公共图书馆。
  • Bean: 图书馆里的每一本书都是一个 Bean。
  • 单例 Bean: 想象一下图书馆里只有 一本 特别重要的参考书(比如《Spring 官方文档》),所有想查阅这本书的人(线程)都必须共用这一本。这就是单例 Bean。
  • 多例 Bean (Prototype): 想象一下图书馆里有很多本同一本书(比如《Java 编程入门》),每个人都可以拿一本自己的去读。这就是多例 Bean。
  • Bean 的状态: 书籍的内容就是 Bean 的状态。
  • 可变状态: 如果这本书允许你在上面做笔记、划线、修改内容,那么这本书就是具有可变状态的。
  • 不可变状态: 如果这本书不允许任何修改,只能阅读,那么这本书就是具有不可变状态的。
  • 线程: 来图书馆查阅书籍的每个人就是一个线程。

现在,我们来套用类比来理解线程安全问题:

  • 单例 Bean (只有一本参考书): 如果多个读者(线程)同时想要在同一本参考书(单例 Bean)上做笔记(修改状态),就会产生冲突。第一个读者写了一半,第二个读者也开始写,内容就会混乱。这就是 线程不安全
  • 多例 Bean (很多本入门书): 如果每个读者(线程)都拿一本自己的入门书(多例 Bean),他们可以在自己的书上随意做笔记(修改状态),互不影响。这就是 线程安全
  • 不可变状态的单例 Bean (只能阅读的参考书): 如果这本参考书不允许做任何修改,多个读者(线程)同时阅读(访问不可变状态),他们不会互相干扰。尽管是同一本书,但因为内容不可修改,所以是 线程安全 的。
  • 可变状态的单例 Bean (允许做笔记的参考书): 如果这本参考书允许做笔记,多个读者(线程)同时做笔记,就会产生线程不安全问题。

2. 最佳实践与解决方案

禁止方案:滥用prototype作用域

  • 问题:每次请求创建新Bean实例,导致内存飙升、GC压力增大,违背单例设计初衷。
  • 适用场景:仅当Bean需要持有请求级状态(如用户会话数据)时使用。

推荐方案(按优先级排序)

方案适用场景实现方式案例
无状态设计绝大多数业务逻辑移除成员变量,用局部变量/参数传递数据Service层业务方法
ThreadLocal线程绑定的数据(如用户身份)ThreadLocal<UserContext>权限校验、数据库路由
同步锁(synchronized)低并发场景的简单状态synchronized方法/代码块本地计数器
并发工具类复杂状态管理AtomicInteger, ConcurrentHashMap分布式ID生成、缓存
不可变对象配置类等只需初始化的数据final修饰字段,无setter方法系统参数配置Bean

3. 生产环境中的典型案例

Case 1:订单服务统计

@Service
public class OrderService {// 错误!多线程下totalOrders可能少加private long totalOrders = 0; // 正确方案:使用AtomicLongprivate final AtomicLong totalOrders = new AtomicLong(0);public void placeOrder() {// 业务逻辑...totalOrders.incrementAndGet();}
}

Case 2:用户会话存储

@Service
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {  // 使用request作用域替代单例private String userId;// getter/setter...
}// 更优方案:ThreadLocal(避免创建过多对象)
public class UserContext {private static final ThreadLocal<String> USER_HOLDER = new ThreadLocal<>();public static void setUserId(String id) { USER_HOLDER.set(id); }public static String getUserId() { return USER_HOLDER.get(); }
}

4. 关键总结

  1. 默认规则:Spring单例Bean非线程安全,安全与否取决于开发者的设计
  2. 黄金准则:优先设计无状态Bean,必须维护状态时用并发工具ThreadLocal
  3. 避坑指南
    • 避免在单例Bean中定义非final成员变量
    • 慎用prototype作用域
    • 同步锁范围要最小化(锁方法不如锁代码块)

延伸思考:为什么Spring MVC的Controller默认单例却安全?
:Controller中处理的HttpServletRequest和响应对象本质是每个请求独享(由Tomcat线程池分配),与单例Controller实例无关。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912859.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912859.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地项目上传git

将您本地的项目代码上传到一个私有的、别人看不见的 GitHub 仓库&#xff0c;是进行云端协作&#xff08;如使用 Google Colab&#xff09;、版本控制和代码备份的最佳实践。这是一个非常重要的技能。 整个过程可以分为三个部分&#xff1a; 准备工作&#xff1a;在您的电脑上…

【.NET Framework 窗体应用程序项目结构介绍】

在使用 Visual Studio (VS) 开发 .NET Framework 窗体应用程序&#xff08;Windows Forms App&#xff09; 时&#xff0c;项目结构通常包含以下核心文件夹和文件。以下是详细介绍&#xff1a; 1. 项目根目录下的主要文件 (1) .csproj 文件 作用&#xff1a;C# 项目文件&…

【SpringAI】4.多模态提问

SpringAI多模态提问 概述 SpringAI支持多模态输入&#xff0c;允许AI模型同时处理文本和图像内容。这对于需要视觉理解的AI应用场景非常有用&#xff0c;如图像描述、视觉问答、图像分析等。 核心概念 1. Media类 SpringAI使用Media类来表示多模态内容&#xff0c;支持图…

自动化提示工程:未来AI优化的关键突破

自动化提示工程:未来AI优化的关键突破 自动化提示工程能够自动化或半自动化地生成或优化提示词,以探索大规模的提示词组合,并通过 自动优化技术提升提示词生成的稳定性。 依据自动化提示工程实现形式在逻辑推理和效能导向 两个维度的取舍上,将其分为基于思维链的自动化提示工…

多模态大语言模型arxiv论文略读(148)

A Comprehensive Survey and Guide to Multimodal Large Language Models in Vision-Language Tasks ➡️ 论文标题&#xff1a;A Comprehensive Survey and Guide to Multimodal Large Language Models in Vision-Language Tasks ➡️ 论文作者&#xff1a;Chia Xin Liang, P…

关于.net core开发的实体所有注解详解

以下是对 .NET Core 开发中实体类&#xff08;用于数据模型&#xff09;和 Web API 控制器/方法&#xff08;用于定义接口&#xff09;常用注解属性&#xff08;Attributes&#xff09;的详细说明与示例&#xff0c;涵盖数据验证、API 行为控制、序列化、Swagger/OpenAPI 文档生…

【安全工具】SQLMap 使用详解:从基础到高级技巧

目录 简介 一、安装与基础配置 1. 安装方法 2. 基本语法 二、基础扫描技术 1. 简单检测 2. 指定参数扫描 3. 批量扫描 三、信息收集 1. 获取数据库信息 2. 获取当前数据库 3. 获取数据库用户 4. 获取数据库版本 四、数据提取技术 1. 列出所有表 2. 提取表数据 …

Redis大Key拆分实战指南:从问题定位到落地优化

引言 最近在项目里遇到一个棘手问题&#xff1a;生产环境的Redis突然变“卡”了&#xff01;查询延迟从几毫秒飙升到几百毫秒&#xff0c;监控面板显示某个节点CPU使用率飙到90%。排查半天才发现&#xff0c;原来是某个用户订单的Hash Key太大了——单Key存了100多万个订单字段…

RabbitMQ简单消息发送

RabbitMQ简单消息发送 简单代码实现RabbitMQ消息发送 需要的依赖 <!--rabbitmq--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>x.x.x</version>&l…

【阅读笔记】基于双边滤波改进的空域滤波算法

一、双边滤波空域滤波算法 双边滤波是一种典型的非线性滤波算法。基于高斯滤波&#xff0c;双边滤波利用强度的变化来保存边缘信息&#xff0c;解决了边缘模糊在视觉观感上认为重要信息丢失的问题。双边滤波的滤波效果主要取决于两个参数&#xff1a;两个像素的空间邻近性和灰…

华为交换机堆叠与集群技术深度解析附带脚本

一、引言 在企业园区网、数据中心等网络场景中&#xff0c;为了提升网络的可靠性、扩展性和管理效率&#xff0c;华为交换机提供了堆叠&#xff08;Stack&#xff09;和集群&#xff08;CSS&#xff0c;Cluster Switch System &#xff09;技术。这两种技术能够将多台物理交换…

Python网络爬虫(十三)- 数据解析模块 BeautifulSoup

1、BS4简介 BeautifulSoup(简称 BS4) 是一个用于解析 HTML 和 XML 文档的 Python 第三方库。它能够从网页或其他 HTML/XML 格式的文本中提取数据,并将其转换为结构化的对象,方便开发者快速定位、提取和操作所需信息。它的核心功能是通过解析器将无序的标记语言转换为树形结…

如何使用 Pytorch Lightning 启用早停机制

【PL 基础】如何启用早停机制 摘要1. on_train_batch_start()2. EarlyStopping Callback 摘要 本文介绍了两种在 PyTorch Lightning 中实现早停机制的方法。第一种是通过重写on_train_batch_start()方法手动控制训练流程&#xff1b;第二种是使用内置的EarlyStopping回调&#…

深入理解前缀和与差分算法及其C++实现

前缀和与差分是算法竞赛和编程中非常重要的两种技巧&#xff0c;它们能够高效地处理区间查询和区间更新问题。本文将详细介绍这两种算法的原理、应用场景以及C实现。 一、前缀和算法 1.1 前缀和的基本概念 前缀和&#xff08;Prefix Sum&#xff09;是一种预处理技术&#x…

HugeGraph【部署】Linux单机部署

注: hugegraph从版本 1.5.0 开始&#xff0c;需要 Java11 运行时环境 一、安装JDK11 1.下载JDK11 https://www.oracle.com/java/technologies/downloads/#java11 2.解压缩包 tar -zxvf jdk-11.0.27_linux-x64_bin.tar.gz 3.修改/etc/profile环境变量 export JAVA_HOME/usr…

C++异步编程里避免超时机制

C标准库中时钟&#xff08;Clock&#xff09; 这段内容主要介绍了C标准库中**时钟&#xff08;Clock&#xff09;**的概念和分类&#xff0c;以及它们在时间测量中的作用。以下是关键信息的解读&#xff1a; 一、时钟的核心特性 C中的时钟是一个类&#xff0c;提供以下四个基…

npm install安装不成功(node:32388)怎么解决?

如果在执行 npm install 时出现问题&#xff0c;尤其是 node:32388 相关的错误&#xff0c;这通常意味着某些依赖或配置出了问题。这里有一些常见的解决方法&#xff0c;你可以尝试&#xff1a; 1. 清除 npm 缓存 有时候&#xff0c;npm 缓存问题会导致安装失败。你可以清除 …

Ubuntu-18.04-bionic 的apt的/etc/apt/sources.list 更换国内镜像软件源 笔记250702

Ubuntu-18.04-bionic 的apt的/etc/apt/sources.list更换国内镜像软件源 笔记250702 为 Ubuntu 18.04 LTS&#xff08;代号 Bionic Beaver&#xff09;更换 /etc/apt/sources.list 为国内镜像源 备份/etc/apt/sources.list文件 sudo cp -a /etc/apt/sources.list /etc/apt/sou…

【运维系列】【ubuntu22.04】安装GitLab

一.下载安装文件 rootgitlab:~# wget https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/9/gitlab-ce-17.4.0-ce.0.el9.x86_64.rpm二.执行安装脚本 2.1 先执行安装前的命令 rootgitlab:~# apt install -y perl-interpreter rootgitlab:~# apt install -y openssh-s…

Cisco ASA防火墙查看ACL的条目数量

这里显示的条目数量为ACE, ACE是啥&#xff1f; ACE全称&#xff1a; access-list entry ACE指的是ACL条目展开后的数量&#xff0c; 啥叫展开&#xff1f; 示例&#xff1a; access-list out-in extend permit tcp80&443 host 1.1.1.1 host 2.2.2.2这种配置是占1条&#…