Spring Bean 作用域设置为prototype在并发场景下是否是线程安全的

news2025/3/4 14:38:47

在并发场景下,将 Spring Bean 作用域设置为 prototype 通常能在一定程度上保证线程安全,但这并不意味着绝对的线程安全

1. prototype 作用域的特点

在 Spring 中,Bean 的作用域定义了 Bean 的生命周期和可见性。prototype 作用域表示每次从 Spring 容器中获取 Bean 时,容器都会创建一个新的 Bean 实例。这与 singleton 作用域不同,singleton 作用域的 Bean 在整个 Spring 容器中只有一个实例。

2. 为何通常能在一定程度上保证线程安全

由于每次请求都会创建一个新的 Bean 实例,不同线程获取到的是不同的 Bean 对象。因此,各个线程对 Bean 的操作不会相互影响,避免了多个线程同时访问和修改同一个 Bean 实例的状态,从而减少了线程安全问题的发生。

以下是一个简单的示例代码:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

// 配置类
@Configuration
class AppConfig {
    @Bean
    @Scope("prototype")
    public MyBean myBean() {
        return new MyBean();
    }
}

// 自定义 Bean 类
class MyBean {
    private int count = 0;

    public void increment() {
        count++;
        System.out.println(Thread.currentThread().getName() + " - Count: " + count);
    }
}

// 主类
public class PrototypeScopeExample {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 创建两个线程
        Thread thread1 = new Thread(() -> {
            MyBean bean1 = context.getBean(MyBean.class);
            for (int i = 0; i < 3; i++) {
                bean1.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            MyBean bean2 = context.getBean(MyBean.class);
            for (int i = 0; i < 3; i++) {
                bean2.increment();
            }
        });

        // 启动线程
        thread1.start();
        thread2.start();

        try {
            // 等待线程执行完毕
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 关闭 Spring 容器
        context.close();
    }
}

在上述代码中,MyBean 的作用域为 prototypethread1thread2 分别获取到不同的 MyBean 实例,它们对各自实例的 count 变量进行操作,不会相互干扰。

3. 为何不是绝对的线程安全

虽然 prototype 作用域的 Bean 本身不会被多个线程共享,但如果 Bean 内部引用了其他 singleton 作用域的 Bean,并且这些 singleton Bean 不是线程安全的,那么仍然可能会出现线程安全问题。

例如:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

// 配置类
@Configuration
class AppConfig2 {
    @Bean
    @Scope("prototype")
    public MyPrototypeBean myPrototypeBean() {
        return new MyPrototypeBean();
    }

    @Bean
    public MySingletonBean mySingletonBean() {
        return new MySingletonBean();
    }
}

// 单例 Bean 类
class MySingletonBean {
    private int sharedCount = 0;

    public void incrementSharedCount() {
        sharedCount++;
        System.out.println(Thread.currentThread().getName() + " - Shared Count: " + sharedCount);
    }
}

// 原型 Bean 类
class MyPrototypeBean {
    private final MySingletonBean singletonBean;

    public MyPrototypeBean() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig2.class);
        this.singletonBean = context.getBean(MySingletonBean.class);
    }

    public void doSomething() {
        singletonBean.incrementSharedCount();
    }
}

// 主类
public class PrototypeWithSingletonExample {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig2.class);

        // 创建两个线程
        Thread thread1 = new Thread(() -> {
            MyPrototypeBean bean1 = context.getBean(MyPrototypeBean.class);
            for (int i = 0; i < 3; i++) {
                bean1.doSomething();
            }
        });

        Thread thread2 = new Thread(() -> {
            MyPrototypeBean bean2 = context.getBean(MyPrototypeBean.class);
            for (int i = 0; i < 3; i++) {
                bean2.doSomething();
            }
        });

        // 启动线程
        thread1.start();
        thread2.start();

        try {
            // 等待线程执行完毕
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 关闭 Spring 容器
        context.close();
    }
}

在这个示例中,MyPrototypeBeanprototype 作用域的 Bean,但它内部引用了 MySingletonBean 这个 singleton 作用域的 Bean。多个 MyPrototypeBean 实例可能会同时访问和修改 MySingletonBeansharedCount 变量,从而导致线程安全问题。

综上所述,将 Spring Bean 作用域设置为 prototype 可以在一定程度上避免线程安全问题,但不能完全保证线程安全,需要根据 Bean 的具体实现和依赖关系进行综合考虑。

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

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

相关文章

金融项目实战

测试流程 测试流程 功能测试流程 功能测试流程 需求评审制定测试计划编写测试用例和评审用例执行缺陷管理测试报告 接口测试流程 接口测试流程 需求评审制定测试计划分析api文档编写测试用例搭建测试环境编写脚本执行脚本缺陷管理测试报告 测试步骤 测试步骤 需求评审 需求评…

命令行参数和环境变量 ─── linux第13课

目录 命令行参数 命令行参数列表: 如何实现命令行参数传递到此进程 环境变量 基本概念 常见环境变量 查看环境变量方法 ​编辑 环境变量如何写入 总结: 测试PATH 命令行参数 同一个程序,可以根据命令行参数的不同,表现不同功能 比如:指令中的选项的实现. ls -al…

基于 openEuler 22.09 的 OpenStack Yoga 部署

openEuler 虚拟化环境部署 使用 VMWare Workstation 创建三台 2 CPU、8G内存、100 GB硬盘 的虚拟机 主机 IP 作用 Controller 192.168.184.110 控制节点 Compute 192.168.184.111 计算节点 Storage 192.168.184.112 存储节 一 基础配置 1.1 配置 yum 源 由于 op…

【Linux实践系列】:用c语言实现一个shell外壳程序

&#x1f525;本文专栏&#xff1a;Linux Linux实践项目 &#x1f338;博主主页&#xff1a;努力努力再努力wz 那么今天我们就要进入Linux的实践环节&#xff0c;那么我们之前学习了进程控制相关的几个知识点&#xff0c;比如进程的终止以及进程的等待和进程的替换&#xff0c;…

conda安装及超详细避坑实战

1. Anaconda介绍。 Anaconda是一站式数据科学与机器学习平台&#xff0c;专为开发者、数据分析师设计,并带有python中超过180个科学包及其依赖项。通过 Anaconda&#xff0c;您可以轻松管理数据环境、安装依赖包&#xff0c;快速启动数据分析、机器学习项目。 Anaconda集成了…

LM studio 加载ollama的模型

1.LM 下载&#xff1a; https://lmstudio.ai/ 2.ollama下载&#xff1a; https://ollama.com/download 3.打开ollama&#xff0c;下载deepseek-r1。 本机设备资源有限&#xff0c;选择7B的&#xff0c;执行ollama run deepseek-r1:7b 4.windows chocolatey下载&#xff1a; P…

深入探索像ChatGPT这样的大语言模型-02-POST training supervised finetuning

参考 【必看珍藏】2月6日&#xff0c;安德烈卡帕西最新AI普及课&#xff1a;深入探索像ChatGPT这样的大语言模型&#xff5c;Andrej Karpathy fineweb知乎翻译介绍 fineweb-v1原始连接 fineweb中文翻译版本 Chinese Fineweb Edu数据集 查看网络的内部结果&#xff0c;可以参…

Kaldi环境配置与Aishell训练

一、项目来源 代码来源&#xff1a;kaldi-asr/kaldi: kaldi-asr/kaldi is the official location of the Kaldi project. (github.com) 官网文档&#xff1a;Kaldi: The build process (how Kaldi is compiled) (kaldi-asr.org) 踩着我的同门李思成-CSDN博客填上的坑kaldi环境…

数据集/API 笔记:新加坡PSI(空气污染指数)API

data.gov.sg 数据范围&#xff1a;2016年2月 - 2025年3月 1 获取API方式 curl --request GET \--url https://api-open.data.gov.sg/v2/real-time/api/psi 2 返回数据 API 的数据结构可以分为 3 大部分&#xff1a; 区域元数据&#xff08;regionMetadata&#xff09; →…

【GPU使用】如何在物理机和Docker中指定GPU进行推理和训练

我的机器上有4张H100卡&#xff0c;我现在只想用某一张卡跑程序&#xff0c;该如何设置。 代码里面设置 import os # 记住要写在impot torch前 os.environ[CUDA_VISIBLE_DEVICES] "0, 1"命令行设置 export CUDA_VISIBLE_DEVICES0,2 # Linux 环境 python test.py …

【Java项目】基于SpringBoot的CSGO赛事管理系统

【Java项目】基于SpringBoot的CSGO赛事管理系统 技术简介&#xff1a;采用SpringBoot框架、Java语言、MySQL数据库等技术实现。 系统简介&#xff1a;CSGO赛事管理系统是一个基于B/S架构的管理系统&#xff0c;主要功能包括前台和后台管理模块。前台系统功能模块分为&#xf…

MIPI接口:(4)MIPI CSI-2协议详解(上)

1. 什么是CSI&#xff1f; CSI&#xff08;Camera Serial Interface&#xff09;是MIPI联盟早期制定的摄像头接口标准&#xff0c;主要用于连接摄像头和处理器。 CSI-2是CSI的第二代版本&#xff0c;在原有基础上进行了全面优化&#xff1a; &#xff08;1&#xff09;分层架…

防火墙旁挂组网双机热备负载均衡

一&#xff0c;二层交换网络&#xff1a; 使用MSTPVRRP组网形式 VLAN 2--->SW3为主,SW4 作为备份 VLAN 3--->SW4为主,SW3 作为备份 MSTP 设计 --->SW3 、 4 、 5 运行 实例 1 &#xff1a; VLAN 2 实例 2 &#xff1a; VLAN 3 SW3 是实例 1 的主根&#xff0c;实…

视频教育网站开源系统的部署安装 (roncoo-education)服务器为ubuntu22.04.05

一、说明 前端技术体系&#xff1a;Vue3 Nuxt3 Vite5 Vue-Router Element-Plus Pinia Axios 后端技术体系&#xff1a;Spring Cloud Alibaba2021 MySQL8 Nacos Seata Mybatis Druid redis 后端系统&#xff1a;roncoo-education&#xff08;核心框架&#xff1a;S…

CF 886A.ACM ICPC(Java实现)

题目分析 输入6个值&#xff0c;判断某三个值的和能够等于另外三个值的和 思路分析 首先判断总和是不是一个偶数&#xff0c;如果不是就“NO”。由于小何同学算法不好&#xff0c;只能使用三层for循环强行判断某三个值是否能等于总和的一半&#xff0c;可以就“YES”。 代码 …

Spring Boot 自动装配深度解析与实践指南

目录 引言&#xff1a;自动装配如何重塑Java应用开发&#xff1f; 一、自动装配核心机制 1.1 自动装配三大要素 1.2 自动装配流程 二、自定义自动配置实现 2.1 创建自动配置类 2.2 配置属性绑定 2.3 注册自动配置 三、条件注解深度应用 3.1 常用条件注解对比 3.2 自定…

【windows driver】 开发环境简明安装教程

一、下载路径 https://learn.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads 二、安装步骤&#xff1a; 1、安装Visual Studio IDE 笔者建议安装最新版本&#xff0c;可以向下兼容。发文截止到目前&#xff0c;VS2022是首选&#xff0c;当前笔者由于项…

探秘基带算法:从原理到5G时代的通信变革【八】QAM 调制 / 解调

文章目录 2.7 QAM 调制 / 解调2.7.1 概述2.7.2 星座图星座图的结构与性能发射端的信息编码与接收端的解码差分编码的分类与实现差分编码的模4格雷加法器公式16QAM星座图与映射关系 2.7.3 信号表达式正交振幅调制的基本原理与系统分析相位误差对QAM性能的影响多电平正交振幅调制…

Flink性能指标详解MetricsAnalysis

文章目录 Flink 组成1.JobManager2.TaskManager3.ResourceManager4.Dispatcher5.Client6. Env JobManager MetricsTaskManager Metrics Flink 组成 1.JobManager 管理任务 作业调度&#xff1a;负责接收和调度作业&#xff0c;分配任务到 TaskManager。资源管理&#xff1a;…

Halcon 车牌识别-超精细教程

车牌示例 流程: 读取图片转灰度图阈值分割,找车牌内容将车牌位置设置变换区域形状找到中心点和弧度利用仿射变换,斜切车牌旋转转正,把车牌抠出来利用形态学操作拼接车牌号数字训练ocr开始识别中文车牌 本文章用到的算子(解析) Halcon 算子-承接车牌识别-CSDN博客 rgb1_to_gray…