spring中的并发隐患


四种常见的scope属性

singleton scope

在spring容器中,当一个bean被声明成singleton时,容器初始化的时候就会生成一个实例,所有请求调用指向的都是同一个实例,这也是spring中bean定义的默认属性
这里写图片描述

prototype scope

与singleton属性完全不同,每次引用都会导致一个新的实例的创建,和new操作很像
这里写图片描述

request scope

每一次http请求都会创建一个实例,当http请求生命周期结束的时候,实例自动销毁

session scope

与http请求的不同的是,在每一次http请求的session生命周期内只创建一个实例,在http请求session生命周期(浏览器默认一次session回话的生命周期为30min)结束的时候,实例自动销毁

不同scope的线程安全性

这应该是大家在都考虑过的一个问题,用一个简单的例子来说明

@Controller
@ResponseMapping(value = "/Test")
@Scope("singleton") /**这里根据要求,切换不同scope属性 **/
public class TestScope {

    private int i;
    @ResponseMapping("scopeInt")
    public String value(){
        i++;
        System.out.println(i);
        return "index";
    }
}

不同scope下的结果分析

singleton

这里写图片描述
当bean属性定义为singleton时,我们在浏览器上每一次发送请求的结果都会受到上一次的影响,在同一台电脑上用不同的浏览器如此,用不同的电脑发送亦如此!这也就是说,如果不同的用户调用这个bean实例的时候会相互影响,这将是一件非常恐怖的事情。

prototype

这里写图片描述

每次请求的结果都是1,因为每次调用都会创建一个实例,各自互不影响,所以没有发生上面那种串数据的情况

request

这里写图片描述

和prototype的情况一样,每次结果都是1,每个request请求都会导致spring容器内创建一个实例,各实例互不影响。

session

这里写图片描述
这个比较有意思,在同一个浏览器下,每次请求的结果会都彼此影响。在同一台电脑下,使用不同浏览器请求,请求结果彼此独立,即使用浏览器2发送请求的结果不会受到浏览器1请求的影响,也就是说在浏览器的session生命周期内spring容器中只创建了一个实例,session的生命周期结束,容器内的实例也随之销毁

request 和 prototype的区别

上面的结果中,bean在request属性下和prototype属性下产生的结果一样,而且原理似乎也相同,每次请求创建一个实例,但是他们还是有着很大的区别:
1.应用场景不一样:request请求下创建bean需要对http请求进行拦截监听,http请求发生,实例创建,http请求结束,实例销毁。prototype模式则不需要对http请求进行拦截,任何调用都会创建一个新的实例

2.生命周期不一样:request模式下的bean实例生命周期很短,当次request请求的生命周期就是bean实例的生命周期,容器中的bean实例对象会伴随着request请求的生命周期结束而销毁。prototype的生命周期不完全受到spring容器的管理,也就是说,当对bean实例的调用结束之后它还是会驻留在容器中,如果需要清除prototype模式下的bean实例和它所持有的资源,需要额外的代码来做相应处理。

singleton模式下要注意的问题

前面已经说过,在spring中,bean的默认属性是singleton,而在singleton模式下,spring并不保证线程安全,所以将bean声明为singleton时一定要注意线程安全性问题。
在上面的例子程序中,之所有会出现不同的请求间会发生串数据的情况,主要是因为定义了bean的状态(state),也就是给class定义了一个成员变量 int i。在singleton模式下,bean不能定义为有状态,因为每个线程调用的是同一个实例,有可能会修改实例的状态。

针对这种情况有两种解决方案:
1.将变量定义在方法中。线程可以理解为一系列方法的有序执行,而每个线程都有自己独立的栈帧空间,方法中的变量在线程栈内局部有效
2.用ThreadLocal类将私有成员变量进行包装。ThreadLocal类会为每个线程创建一个变量副本

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值