Spring(十一):Spring Bean 是线程安全的吗?

Spring 中的默认为所有申明为 Bean 的对象创建一个实例存放到IoC容器进行管理的,这些Bean对象对于多线程来说是共享的,所以严格来说 Spring Bean 是非线程安全的。Spring 本身就没有对 bean 的多线程安全问题做出任何保证与措施。   

作用域

Spring Bean 的线程安全还得根据应用场景和申明的作用范围来分析:

通常,对所有 有状态 Bean 申明为原型范围(protopyte),对无状态 Bean 申明为单例范围(singleton)。

  • 有状态:有数据存储功能。如,定义了成员变量。
  • 无状态:不会保存数据,就不存在状态被修改的情况。

单例

通常,Spring 默认创建的 Bean 是单例的(作用域:singleton),是一个无状态 Bean,不会因为多线程破坏对象状态,即访问线程不会对 Bean 的成员执行执行查询以外的操作,那么这个单例 Bean 可以认为是线程安全的。如 Controller、Service、Dao 等也是由 Spring 容器管理的,这类 Bean 大多是无状态的,只关注于方法本身。

原型

解决 SpringBean的线程安全问题,最简的办法是把Bean的作用域由默认的singleton修改为prototype,每次调用都创建一个新的对象,但如果定义了静态成员变量,仍然不是线程安全的,静态成员变量会被改变。

对于每个bean的线程安全问题,根本原因是每个bean自身的设计。不要在bean中声明任何有状态的实例变量或类变量,如果必须如此,那么就使用 ThreadLocal 把变量变为线程私有的;如果bean的实例变量或类变量需要在多个线程之间共享,那么就只能使用synchronized、lock、CAS等这些实现线程同步的方法了。

参考资料

  1. 聊一聊 Spring 中的线程安全性

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

Spring(十一):Spring Bean 是线程安全的吗?

http://blog.gxitsky.com/2018/04/01/Spring-11-bean-thread-safety/

作者

光星

发布于

2018-04-01

更新于

2022-06-17

许可协议

评论