Spring中采用公共变量并发问题解决-阿里云开发者社区

开发者社区> fuyifang> 正文

Spring中采用公共变量并发问题解决

简介: 由于系统采用springmvc框架,springmvc核心控制器DispatcherServlet 默认为每个controller生成单一实例来处理所有用户请求,所以在这个单一实例的controller中,它的XXXService也是一个实例处理所有请求, 这样XXXService的成员变量就被所有请求共享。
+关注继续查看

由于系统采用springmvc框架,springmvc核心控制器DispatcherServlet 默认为每个controller生成单一实例来处理所有用户请求,所以在这个单一实例的controller中,它的XXXService也是一个实例处理所有请求, 这样XXXService的成员变量就被所有请求共享。这样就会出现并发请求时变量内容被篡改的问题。

那么出现这种问题如何解决呢?
第一种方式: 既然是全局变量惹的祸,那就将全局变量都编程局部变量,通过方法参数来传递,但是如果多个方法都需要该参数的话,传参就相当繁琐。
第二种方式: jdk提供了java.lang.ThreadLocal,它为多线程并发提供了新思路。 (当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本)
ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型。
总结:ThreadLocal不是为了解决多线程访问共享变量,而是为每个线程创建一个单独的变量副本,提供了保持对象的方法和避免参数传递的复杂性。

父类ThreadLocal定义:

//存储MessageContentModel对象,防止对象并发覆盖
    private ThreadLocal<MessageContentModel> msgContentModelTL = new ThreadLocal<MessageContentModel>();
    //存储HandlerContext对象,防止对象并发覆盖
    private ThreadLocal<HandlerContext> contextModelTL = new ThreadLocal<HandlerContext>();

父类设置对象值:

 /**
     * 日志对象
     */
    public HandlerContext getContext() {
        return contextModelTL.get() != null ? contextModelTL.get() : new HandlerContext();
    }

    private void setContext(HandlerContext context) {
        contextModelTL.set(context);
    }

    /**
     * 消息内容服务公用模型
     */
    public MessageContentModel getMsgContentModel() {
        return msgContentModelTL.get() != null ? msgContentModelTL.get() : new MessageContentModel();
    }

    private void setMsgContentModel(MessageContentModel msgContentModel) {
        msgContentModelTL.set(msgContentModel);
    }

子类使用:

 this.getContext().writeLogTag("获取链接失败");

ThreadLocal的主要应用场景为按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。例如:同一个网站登录用户,每个用户服务器会为其开一个线程,每个线程中创建一个ThreadLocal,里面存用户基本信息等,在很多页面跳转时,会显示用户信息或者得到用户的一些信息等频繁操作,这样多线程之间并没有联系而且当前线程也可以及时获取想要的数据。

实现原理:
ThreadLocal可以看做是一个容器,容器里面存放着属于当前线程的变量。ThreadLocal类提供了四个对外开放的接口方法,这也是用户操作ThreadLocal类的基本方法:
(1) void set(Object value)设置当前线程的线程局部变量的值。
(2) public Object get()该方法返回当前线程所对应的线程局部变量。
(3) public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
(4) protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次,ThreadLocal中的缺省实现直接返回一个null。

可以通过上述的几个方法实现ThreadLocal中变量的访问,数据设置,初始化以及删除局部变量,那ThreadLocal内部是如何为每一个线程维护变量副本的呢?

其实在ThreadLocal类中有一个静态内部类ThreadLocalMap(其类似于Map),用键值对的形式存储每一个线程的变量副本,ThreadLocalMap中元素的key为当前ThreadLocal对象,而value对应线程的变量副本,每个线程可能存在多个ThreadLocal。

http://blog.csdn.net/lhqj1992/article/details/52451136

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
局部变量和成员变量的初始值问题
引言 大家都知道,在java中,成员变量是可以不用给初始值的,默认就有一个初始值。而局部变量,必须显示给予一个初始值,否则编译无法通过。大家在学习的时候,一般是直接把这个结论直接记下,很少去考虑原因。
574 0
稳定性专题 | Spring Boot 常见错误及解决方法
导读 『StabilityGuide』是阿里多位阿里技术工程师共同发起的稳定性领域的知识库开源项目,涵盖性能压测、故障演练、JVM、应用容器、服务框架、流量调度、监控、诊断等多个技术领域,以更结构化的方式来打造稳定性领域的知识库,欢迎您的加入。
5664 0
【高并发】一文解密诡异并发问题的第一个幕后黑手——可见性问题
可见性问题,可以这样理解:一个线程修改了共享变量,另一个线程不能立刻看到,这是由CPU添加了缓存导致的问题。理解了什么是可见性,再来看可见性问题就比较好理解了。既然可见性是一个线程修改了共享变量后,另一个线程能够立刻看到对共享变量的修改,如果不能立刻看到,这就会产生可见性的问题。
49 0
spring如何解决循环依赖
首先搞懂一个概念,解决循环依赖并不是靠我们,spring会帮我们解决 但是!!!记住一点,很重要
11 0
SpringBoot Jpa 使用问题解决整合
1. 启动项目报错 Not a managed type: class com.xzxx 这种问题一般出在多模块开发中的依赖传递导致的问题,该问题的原因是启动类找不到对应的bean。
920 0
【高并发】解密导致并发问题的第二个幕后黑手——原子性问题
原子性是指一个或者多个操作在CPU中执行的过程不被中断的特性。原子性操作一旦开始运行,就会一直到运行结束为止,中间不会有中断的情况发生。
60 0
SpringMVC的JSP页面中中EL表达式不起作用的问题解决
今天,我在写SpringMVC代码的时候遇到了一个问题,就是在jsp页面中使用el表达式取值,取不到值,但是使用jsp中嵌套java代码可以取到值。
883 0
UNITY3D的变量初始化问题
大部分是代码声明变量,而变量的初始化值在编辑器中指定,不在代码中直接指定 奇怪! 而且只有Public的才能在编辑器中出现,如果你改为Private就不再显示,如果你再改回PUBLIC,原先指定的初化值会丢失!
760 0
解决tomcat引入spring容器出错
错误1: log4j:WARN Please initialize the log4j system properly. 2013-1-15 20:22:28 org.apache.catalina.core.StandardContext filterStart 严重: Exception starting filter struts2 Class: com.opensympho
1324 0
+关注
fuyifang
携程旅行网技术研发中心资深研发工程师,研发Leader;CSDN博客专家;
260
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载