Spring 中的bean 是线程安全的吗?

结论:不是线程安全的

Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。

Spring 的 bean 作用域(scope)类型

  • singleton:单例,默认作用域。
  • prototype:原型,每次创建一个新对象。
  • request:请求,每次Http请求创建一个新对象,适用于WebApplicationContext环境下。
  • session:会话,同一个会话共享一个实例,不同会话使用不用的实例。
  • global-session:全局会话,所有会话共享一个实例。

线程安全这个问题,要从单例与原型Bean分别进行说明。

原型Bean

对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。

单例Bean

对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。

如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。

spring单例,为什么controller、service和dao确能保证线程安全?

Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理。

实际上大部分时间Bean是无状态的(比如Dao) 所以说在某种程度上来说Bean其实是安全的。

但是如果Bean是有状态的 那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。

  • 有状态就是有数据存储功能
  • 无状态就是不会保存数据 controller、service和dao层本身并不是线程安全的,只是如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。

Java虚拟机栈是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

局部变量的固有属性之一就是封闭在执行线程中。它们位于执行线程的栈中,其他线程无法访问这个栈。

所以其实任何无状态单例都是线程安全的。

Spring的根本就是通过大量这种单例构建起系统,以事务脚本的方式提供服务。

首先问@Controller @Service是不是线程安全的?

答:默认配置下不是的。为啥呢?因为默认情况下@Controller没有加上@Scope,没有加@Scope就是默认值singleton,单例的。意思就是系统只会初始化一次Controller容器,所以每次请求的都是同一个Controller容器,当然是非线程安全的。举个栗子:
在这里插入图片描述

在postman里面发三次请求,结果如下:

说明他不是线程安全的。怎么办呢?可以给他加上上面说的@Scope注解,如下:

在这里插入图片描述

这样一来,每个请求都单独创建一个Controller容器,所以各个请求之间是线程安全的,三次请求结果:

在这里插入图片描述

加了@Scope注解多的实例prototype是不是一定就是线程安全的呢?

在这里插入图片描述

看三次请求结果:

在这里插入图片描述

虽然每次都是单独创建一个Controller但是扛不住他变量本身是static的呀,所以说呢,即便是加上@Scope注解也不一定能保证Controller 100%的线程安全。所以是否线程安全在于怎样去定义变量以及Controller的配置。

所以来个全乎一点的实验,代码如下:

在这里插入图片描述

补充Controller以外的代码:

config里面自己定义的Bean:User

在这里插入图片描述

我暂时能想到的定义变量的方法就这么多了,三次http请求结果如下:

在这里插入图片描述

可以看到,在单例模式下Controller中只有用ThreadLocal封装的变量是线程安全的。为什么这样说呢?我们可以看到3次请求结果里面只有ThreadLocal变量值每次都是从0+1=1的,其他的几个都是累加的,而user对象呢,默认值是0,第二交取值的时候就已经是1了,关键他的hashCode是一样的,说明每次请求调用的都是同一个user对象。

下面将TestController 上的@Scope注解的属性改一下改成多实例的:@Scope(value = “prototype”),其他都不变,再次请求,结果如下:

在这里插入图片描述

分析这个结果发现,多实例模式下普通变量,取配置的变量还有ThreadLocal变量都是线程安全的,而静态变量和user(看他的hashCode都是一样的)对象中的变量都是非线程安全的。

也就是说尽管TestController 是每次请求的时候都初始化了一个对象,但是静态变量始终是只有一份的,而且这个注入的user对象也是只有一份的。静态变量只有一份这是当然的咯,那么有没有办法让user对象可以每次都new一个新的呢?当然可以:

在这里插入图片描述

在config里面给这个注入的Bean加上一个相同的注解@Scope(value = “prototype”)就可以了,再来请求一下看看:

在这里插入图片描述

可以看到每次请求的user对象的hashCode都不是一样的,每次赋值前取user中的变量值也都是默认值0。

下面总结一下:

1、在@Controller/@Service等容器中,默认情况下,scope值是单例-singleton的,也是线程不安全的。

2、尽量不要在@Controller/@Service等容器中定义静态变量,不论是单例(singleton)还是多实例(prototype)他都是线程不安全的。

3、默认注入的Bean对象,在不设置scope的时候他也是线程不安全的。

4、一定要定义变量的话,用ThreadLocal来封装,这个是线程安全的

举报/反馈

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

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

相关文章

天文学专业在什么时候学计算机,南京大学在985排名第几?南京大学最牛的专业是天文系吗?...

选择科目测一测我能上哪些大学选择科目领取你的专属报告>选择省份关闭请选择科目确定v>百年名校南京大学坐落于金陵古都,文化底蕴深厚,是不少考生向往的“211”“985”“双一流”高校。本期圆梦志愿就来带大家看看这所学校在全国985高校中的排名情…

Java中的ThreadLocal详解

一、ThreadLocal简介 多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。ThreadLocal是除了加锁这种同…

计算机专用英语词汇pdf,计算机专用英语词汇1500词.pdf

计算机专用英语词汇1500 词 36. memory n. 记忆存储,存储器37. which pron. 哪个,a. 那一个Sample TextSample Text 38. all a. 全,全部;ad. 完全电脑日常用语和术语大集合~~ !!! 39. on ad. 接…

谈谈对ThreadLocal的理解?(基于jdk1.8)

在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余。 这篇文章主要从以下几个角度来…

江苏学考计算机,学长建议 江苏考生 位次在4000-10000 想报考计算机的同学

本人对高考志愿填报有点执念,毕竟是第一次真正重大的抉择,以后每年都会看看高校录取情况,加上今年刚找工作,对互联网企业的选人标准比较了解,所以斗胆来提提建议。核心观点,多看看985的分校区,比…

mybatis if test判断 list不为空

<if test"list!null and list.size()!0"></if>注意 如果使用list.isNotEmpty()会报错&#xff0c;提示不是一个方法

数字时钟html5 js,html5 canvas js(数字时钟)实例代码

canvas dClock您的浏览器太古董了&#xff0c;升级吧&#xff01;var clock document.getElementById("clock");var cxt clock.getContext("2d");//显示数字时钟function showTime(m, n) {cxt.clearRect(0, 0, 500, 500);var now new Date;var hour no…

简单理解BigDecimal.valueof(Double t)与BigDecimal.valueof(String t)的区别——BigDecimal

上面的代码主要的区别在于 初始化BigDecimal时形参是double、String和float的区别 从上面可以看到&#xff0c;当double 和 float 时&#xff0c;实际保存的值并不是是准确的0.99&#xff0c;这是为什么呢 大致的原因是&#xff1a; BigDecimal(double val)将会把double型二…

在线计算机标准版,NCRE全国计算机等级一标准版级考试复习资料.doc

全国计算机等级一级考试复习资料内容&#xff1a;计算机基础知识、文字处理软件WORD复习题类型&#xff1a;填空题、选择题、综合题复习题数量&#xff1a;复习时间&#xff1a;12月5日—12月9日考试时间&#xff1a;12月9日(周三下午第三节课)参考对象&#xff1a;电子高专的学…

mysql 统计当天,本周,本月,上一月的数据

今天 select * from ht_invoice_information where year(create_date)year(date_sub(now(),interval 1 year)); select * from 表名 where to_days(时间字段名) to_days(now());昨天 select * from 表名 where to_days( now( ) ) - to_days( 时间字段名) < 1近期7天 sel…

下图中的蓝月亮为科学家用计算机,2018年高一地理前半期课时练习试卷带答案和解析...

目前人类可以观察到的最高级别天体系统是A. 总星系 B. 银河系 C. 太阳系 D. 地月系【答案】A【解析】本题考查天体系统的层次。距离相近的天体因相互吸引和相互绕转&#xff0c;构成不同级别的天体系统&#xff0c;天体系统的层次为&#xff1a;最高一级为总星系(即目前所知的宇…

邮政计算机网络,邮政计算机网络论文(共2018字).doc

邮政计算机网络论文(共2018字)邮政计算机网络论文(共2018字)一、邮政计算机网络基本现状分析邮政网络系统资源不足&#xff0c;数据传输技术滞后随着邮政储蓄代收付业务和电子邮政业务的快速发展&#xff0c;市场需要变化加快&#xff0c;现有网络系统资源不足&#xff0c;设备…

HashMap的put方法返回值问题

API文档中的描述&#xff1a; 先看一个例子 Map<Character, Integer> map new HashMap<Character, Integer>(); System.out.println(map.put(a, 0)); // null System.out.println(map.put(a, 1)); // 0 System.out.println(map.put(a, 2)); // 1 System.out.pri…

资金时间价值的计算机应用视频讲解,第八章资金时间价值与方案经济比选20161018讲解.ppt...

第八章资金时间价值与方案经济比选20161018讲解(二)净年值(NAV) 1、含义 净年值也称净年金(记作NAV)&#xff0c;它是把项目寿命期内的净现金流量按设定的折现率折算成与其等值的各年年末的等额净现金流量值。 2&#xff0e;计算 先求该项目的净现值&#xff0c;然后乘以资金回…

[Microsoft][ODBC SQL Server Driver][SQL Server]对象名 ‘***‘无效问题的解决方案器

[Microsoft][ODBC SQL Server Driver][SQL Server]对象名 ***无效问题的解决方案 在用Java进行SQL server数据编程时出现数据库连接成功后对表进行操作时报错“表名无效”。在网上搜了相关问题后均未解决&#xff0c;最后通过在表名前加数据库名的方式得以解决&#xff0c;记录…

Java中将Map转换为JSON

一个注意的地方&#xff1a;要选对jar包 Map map new HashMap();map.put("success", "true");map.put("photoList", photoList);map.put("currentUser", "zhang");//net.sf.json.JSONObject 将Map转换为JSON方法JSONObject…

掌上通计算机一级考试在线安装,计算机一级掌上通

计算机一级掌上通app是一款计算机等级考试学习的软件&#xff0c;让你在线学习计算机的操作知识&#xff0c;便于通过等级考试&#xff0c;快速准确&#xff1b;软件提供海量选择题的题库&#xff0c;随时随地做题&#xff0c;简单又方便&#xff0c;还有计算机基本操作讲解&am…

java获取时间,本周,本月,本季度的起始

package com.yong.util; import java.util.Calendar; import java.util.Date;public class TestDate {public static void main(String[] args) {System.out.println("当前时间&#xff1a;" new Date().toLocaleString());System.out.println("当天0点时间&…

东莞理工学院计算机ccf,中国计算机学会东莞分部成立

为更全面和更好地服务东莞计算机领域专业人士的学术和职业发展&#xff0c;在中国计算机学会(CCF)总部和广州、深圳分部的指导和协助下&#xff0c;由东莞理工学院和中美融易孵化器牵头&#xff0c;联合东莞市各大高校、学会、企业&#xff0c;共同发起成立中国计算机学会东莞分…

mybatis获取表名——mybatis动态调用表名和字段名#{},${}

一直在使用Mybatis这个ORM框架&#xff0c;都是使用mybatis里的一些常用功能。今天在项目开发中有个业务是需要限制各个用户对某些表里的字段查询以及某些字段是否显示&#xff0c;如某张表的某些字段不让用户查询到。这种情况下&#xff0c;就需要构建sql来动态传入表名、字段…