Spring框架中的单例bean是线程安全的吗?
Spring bean 并没有可变的状态 ( 比如 Service 类和 DAO 类 ) ,所以在某种程度上说 Spring 的单例 bean是线程安全的。
不是线程安全的,
当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求对应的业务逻辑(成员方法),如果该处理逻辑中有对该单列状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。
Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。
比如:我们通常在项目中使用的Spring bean都是不可可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。
如果你的bean有多种状态的话(比如 View Model对象),就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用由“singleton”变更为“prototype”。
如何处理 Spring 单例有状态的Bean 的线程安全问题?
- 将 Bean 的作用域由 “singleton” 单例 改为 “prototype” 多例。
- 在 Bean 对象中避免定义可变的成员变量,当然,这样做不太现实,就当我没说。
- 在类中定义 ThreadLocal 的成员变量,并将需要的可变成员变量保存在ThreadLocal 中,
- ThreadLocal 本身就具备线程隔离的特性,这就相当于为每个线程提供了一个独立的变量副本,每
- 个线程只需要操作自己的线程副本变量,从而解决线程安全问题