Spring Bean的线程安全问题

对于Proptotype(原型)作用域

普通成员变量是否线程安全。 安全

静态变量线程是否安全。 不安全

对于singletion(单例)作用域

普通成员变量是否线程安全。 不安全

静态变量线程是否安全。 不安全

如何解决

  • 对于单例模式,无论是静态成员变量还是普通成员变量,Spring使用ThreadLocal解决线程安全问题。

  • 可以将singleton作用域改为prototype作用域,因为在prototype作用域下,每次获取都会创建一个新的 bean 实例,不存在资源竞争问题,所以不存在线程安全问题。singleton 作用域下,IoC 容器中只有唯一的 bean 实例,可能会存在资源竞争问题(取决于 Bean 是否有状态)。如果这个 bean 是有状态的话,那就存在线程安全问题(有状态 Bean 是指包含可变的成员变量的对象)。

  • 在 Bean 中尽量避免定义可变的成员变量。

大部分 Bean 实际都是无状态(没有定义可变的成员变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。

有状态Bean (Stateful Bean) :

就是有实例变量的对象,可以保存数据,是非线程安全的。每个用户都有自己特有的实例,在用户的生命周期中,bean保存了用户的信息,即为“偶状态”;一旦用户衰亡(调用结束),bean的生命周期也随之结束。即每个用户最初都会得到一个初始的bean。

无状态Bean (Stateless Bean) :

就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。

在spring中可以使用 @Scope 来控制作用范围通常使用的是

@Scope(“singleton”) 也就是默认值 单例模式(分为无状态bean 和有状态bean,通常我们不会增加变量,只是专注于方法本身不会有数据共享的情况,只是单纯的查操作) @Scope(“prototype”) 多例模式

在spring中无状态的Bean适合用不变模式,就是单例模式,这样可以共享实例提高性能。有状态的Bean在多线程环境下不安全,适合用Prototype原型模式。

总结:

在prototype作用域下,每次获取都会创建一个新的 bean 实例,不管对于有状态的bean和无状态的bean,都不存在线程安全问题,但如果变量是静态的,那就会有线程不安全问题。

在singleton 作用域下,无状态的bean不会有线程安全问题,但对于有状态的bean会有线程安全问题,可以用(threadlocal,改作用域,避免定义可变的成员变量)来解决。

有状态 Bean :包含可变的成员变量的对象

无状态 Bean:没有定义可变的成员变量

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值