单例 Bean 的线程安全问题
最近面试遇到一个问题:单例 Bean 的线程安全问题怎么解决的。
之前了解但是没有深究它的解决方法。大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。
大部分 Bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。
因为Spring 默认情况下是单例的(singleton)。所有我们会遇见多个线程操作同一个对象的时候是存在资源竞争的问题。
常见的有两种解决办法:
在 Bean 中尽量避免定义可变的成员变量。
在类中定义一个
ThreadLocal
成员变量,将需要的可变成员变量保存在ThreadLocal
中(推荐的一种方式)。 在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
而
ThreadLocal
则从另一个角度来解决多线程的并发访问。ThreadLocal
会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。不同线程只操作自己线程的副本变量。ThreadLocal
提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal
。ThreadLocal
代码举例private static ThreadLocal<Integer> content=new ThreadLocal<Integer>(){ protected Integer initalValue(){
return (int)(Math.random()*10+100);
} }; private static ThreadLocal<Integer> test=new ThreadLocal<Integer>(){ protected String initalValue(){
return "单例模式是不安全的" +(int)(Math.random()*10+100);
}
};
public Object get(){
System.out.println(content.get());
System.out.println(test.get());
System.out.println();
return test.get();
}
将有状态的bean的作用域由“singleton”改为“prototype”。( 如注解 : @Scope("prototype") );
使用线程同步,加关键字synchronized。对多线程性能有一定影响(此方法没试验过 慎用!);
单例 Bean 的线程安全问题的更多相关文章
- Spring单例Bean和线程安全
Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框 ...
- Spring框架中的单例bean是线程安全的吗?
不,Spring框架中的单例bean不是线程安全的.
- Spring 框架中的单例 bean 是线程安全的吗?
不,Spring 框架中的单例 bean 不是线程安全的.
- Spring bean 和单例bean的线程安全
Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).prototype(原型).request.session和global session,5种作用域说 ...
- spring单例bean是线程安全的吗?
如果在你不定义成员变量的情况下,spring默认是线程安全的 否则,设置scope="prototype"
- Spring框架中的单例Beans是线程安全的么?
Spring框架并没有对单例bean进行任何多线程的封装处理.关于单例bean的线程安全和并发问题需要开发者自行去搞定.但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和 ...
- 【Spring】8、Spring框架中的单例Beans是线程安全的么
看到这样一个问题:spring框架中的单例Beans是线程安全的么? Spring框架并没有对单例bean进行任何多线程的封装处理.关于单例bean的线程安全和并发问题需要开发者自行去搞定.但实际上, ...
- Spring框架中的单例Beans是线程安全的么
Spring框架并没有对单例bean进行任何多线程的封装处理.关于单例bean的线程安全和并发问题需要开发者自行去搞定.但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和 ...
- 5.2:缓存中获取单例bean
5.2 缓存中获取单例bean 介绍过FactoryBean的用法后,我们就可以了解bean加载的过程了.前面已经提到过,单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例 ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)
代码入口 上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了f ...
随机推荐
- 4.2:Scrapy爬虫
使用Scrapy框架对网站的内容进行爬取 在桌面处打开终端,并在终端中输入: scrapy startproject bitNews cd bitNews/bitNews 修改items文件的内容,输 ...
- Spring IOC源码(二):IOC容器之 刷新前的准备
1.源码解析 prepareRefresh()容器刷新refresh()的第一个方法,是容器刷新前的准备工作. 1 // 容器启动的开始时间 毫秒级 2 private long startupDat ...
- PAM8403 3.3V音频功放调试笔记
做I2S输出用了PT8211(实际上买到的丝印是GH8211), 双声道, LSB格式, 工作正常但是输出功率非常低, 喇叭声音要贴近了才能勉强听到, 所以打算做一个PT8211带功放的I2S模块. ...
- MongoDB - 数据模型的设计模式
简介 官方文章的地址是 Building with Patterns: A Summary,其中汇总了 12 种设计模式及使用场景. 上述的图表列举了 12 种设计模式及应用场景,主要是以下这些: 近 ...
- easygui 之integerbox()、enterbox()、multenterbox() 三种输入函数的使用
1.integerbox()函数:只可输入整数的输入框,默认输入范围为0-99 integerbox(msg="", title=" ", default=No ...
- 基于.NetCore开发博客项目 StarBlog - (25) 图片接口与文件上传
前言 上传文件的接口设计有两种风格,一种是整个项目只设置一个接口用来上传,然后其他需要用到文件的地方,都只存一个引用ID:另一种是每个需要文件的地方单独管理各自的文件.这俩各有优劣吧,本项目中选择的是 ...
- conan环境安装
环境 安装conan 使用conan 搜索包 导入包 编译 打包项目 准备源码 编译成conan包 环境 ubuntu:bionic的docker image docker run -it ubunt ...
- 第三章 --------------------XAML的属性和事件
1.XAML注释是什么样子的? 在之前的章节有提起过,但是这一节我还是想系统的学习XAML,XAML的注释如下 <!-- //这其中填写注释 --> Notice:在注释的部分编译器是不编 ...
- History模式的配置细节
旧文从语雀迁移过来,原日期:2021-09-13 前言 我们知道,vue 单页面应用打包出来是静态资源,一般需要 nginx 或者其他服务器访问:当如果 Vue Router 是采用 History ...
- day12-功能实现11
家居网购项目实现011 以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git 27.功能25-事务管理 27.1下订单问题思考 在生成 ...