阅读 75

springMVC线程安全问题

前言:要知道springmvc线程安全的问题由来,需要对SpringMVC和Struts2做个分析。

SpringMVC是一种基于方法的拦截,而Struts2是基于类的拦截。struct2为每一个请求都实例化一个action所以不存在线程安全问题,springMVC默认单例请求使用一个Controller,如果此Controller中定义了静态变量就会被多个线程共享。所以springMVC的controller尽可能的不要定义静态变量。如果要使用可以用ThreadLocal或者@Scope("prototype")开启不以单例的模式运行,但是以此类方式运行就会有额外的开销。

线程安全:其实就是数据共享(就是出现了竞争关系)问题。

如果多个线程之间共享了同一份数据就存在同时操作此数据的可能。这个时候就可能会出现和预期所要的结果不一致的数据或者一直死锁,这就是线程安全问题。说到多线程共享的问题,Java平台中的内存包括以下几种:Stack、Heap和Non-Heap,其中stack是线程独享的,heap和non-heap是线程间共享的。
stack(栈):每个线程都有自己的栈,其主要用来存放局部变量的值即对象的引用。
heap(堆):所有的对象都是放到堆里面的,实例变量的值是存储在Heap空间的。实例变量是可以被多线程共享的。
non-heap:静态变量的值是存储在Non-Heap空间中的,也是线程间共享的。
有如下的类:

class Test{
    private int a=0;
    private static int b=1;
    public void demo(){
        int c=0;
        boolean flag = true;
        List<String> list=new ArrayList<>();
    }
}复制代码

分析:

其中a是实例变量会被多个线程共享(Test类如果是单列的话)
b是静态变量(类变量)会被多个线程共享
c是局部变量用线程独享的栈存放
list存放指向堆上的对象的引用也是线程独享的。这里还实例化了一个ArrayList对象是放在堆上的这个是可以共享的,但是对例子上的这个对象来讲demo每次被调用都会生成一个ArrayList实例,因此list变量所引用的对象实际上只有一个线程可以访问。以上就是使用单例和多例。单例模式的时候,类里面有静态变量和实例变量的时候就需要考虑线程安全的问题了,此时一些集合操作最好使用java.util.concurrent内的相关方法了。

总结:

springMVC会出现线程安全和他的设计模式有着密切的关系,那么如果不小心在类中定义了类变量,那么这个类变量是被所有请求共享的,这可能会造成多个请求修改该变量的值,会出现和预期所要的结果不一致或异常等。所以在写的时候我们劲量回避此问题,如若需要使用则可以使用ThreadLocal或者@Scope("prototype")来处理共享问题。


作者:又菜又想玩的XXX
链接:https://juejin.cn/post/7025058084280074254


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐