先看下面小段代码,一个controller,一个service。

controller.java代码:
    ........
    @Autowired
     private XXXService xxxService;
    ........
    @RequestMapping("/doXXX.do")
    public void doXXX(){
        .....
        xxxService.saveXXX(String content,....);
        .....
    }
    XXXService.java代码:
    private String content;
    ......
    private void init(){//清空请求参数
        content = null;
        ......
    }
    public boolean saveXXX(String content, ......){
        this.init(content, ...);
        this.content = content;
        //业务逻辑处理
    }

以上这段代码在访问量不构成并发时不会出现什么问题。 但当一个请求还未完成,另一个请求已经开始执行的情况下就会出现问题(并发): 第二个请求执行执行init()方法会将第一个请求的content变量设置为null或它本身的值,这样数据就被篡改了。

编码者这样写的目的是因为content等变量需要在多个方法中使用,而且变量很多,但又不想通过方法参数的方式来传递,故使用成员变量。

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

那么出现这种问题如何解决呢? 
    第一种方式: 既然是全局变量惹的祸,那就将全局变量都编程局部变量,通过方法参数来传递。
    第二种方式: jdk提供了java.lang.ThreadLocal,它为多线程并发提供了新思路。 (当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本)
         那么在什么地方使用ThreadLocal呢? 什么变量是请求公用的就将该变量托付给ThreadLocal来管理其线程副本, 所以我们在xxxService中使用它。
        XXXService.java代码:
        private ThreadLocal<String> contentTL = new ThreadLocal<String>();
        //private String content;使用contentTL代替content;
        ......
        public boolean saveXXX(String content, ......){
            this.contentTL.set(content);

//业务逻辑处理
            //在各方法中使用content时候用this.contentTL.get()代替
    }

此类并发篡改数据的问题,可以在开发工具中设置断点调试的方式来模拟并发。即第一次请求运行到断点时,查看content内容,并且不让程序继续往下运行,同时再发起一个请求,查看content内容。 如内容是第一次请求的内容,并且让第一个请求跑完后,第二个请求到断线处的content正确时,可以确定不会出现并发问题。

spring全局变量引起的并发问题的更多相关文章

  1. Spring全局变量

    压测spring框架的webservice接口,大并发量下响应值与预期值不一致 经查,开发在类中使用全局变量导致: springmvc核心控制器DispatcherServlet 默认为每个contr ...

  2. 询问Spring Bott和高并发框架两个问题

    这里我问两个问题,请大神告诉我. 第一个问题,如果我想用Spring Boot开发企业级的微服务,我该看哪些资料?比如数据库该如何配置?消息中间件该怎么设置?等等.或者可以推荐给我几本这方面的书. 第 ...

  3. Spring 是如何解决并发访问的线程安全性问题的

    springmvc的controller是singleton的(非线程安全的),这也许就是他和struts2的区别吧!和Struts一样,Spring的Controller默认是Singleton的, ...

  4. Spring集成的Quartz 并发

    以前经常在任务调度程序中使用Spring集成的Quartz,这种方式可以用简单的声明式配置即可实现定时任务,并结合了Spring自身的Bean的管理功能,非常方便.配置样本如下: <bean i ...

  5. spring quartz使用多线程并发“陷阱”

    定义一个job:ranJob,设置每秒执行一次,设置不允许覆盖并发执行 <bean id="rankJob" class="com.chinacache.www.l ...

  6. Spring Cloud Gateway、并发编程等等

    2019年 JUC线程池服务ExecutorService接口实现源码分析 Github Page:http://www.throwable.club/2019/07/27/java-concurre ...

  7. volatile修饰全局变量,可以保证并发安全吗?

    今天被人问到volatile能不能保证并发安全? 呵,这能难倒我? 上代码: //电脑太好,100线程起步~public class ThreadTest { private static volat ...

  8. 140、spring webflux 高并发的spring组件

    最近公司可谓是风云变幻,年前说要拆开卖,后来说要整体卖,表示像我这种渣渣,始终逃脱不掉被卖的命运 下面进入正题 spring webflux 是spring 支持的高并发web框架,将每个http请求 ...

  9. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

随机推荐

  1. 基于Python的测试驱动开发实战

    近年来测试驱动开发(TDD)受到越来越多的关注.这是一个持续改进的过程,能从一开始就形成规范,帮助提高代码质量.这是切实可行的而非天马行空的. TDD的全过程是非常简单的.借助TDD,代码质量会得到提 ...

  2. C/C++预处理指令

    预处理指令 Preprocessor Directives define undef ifdef ifndef if endif else and elif line error include 预定 ...

  3. Java并发编程基础

    Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...

  4. \avformat.h(40) : fatal error C1083: 无法打开包括文件:“libavcodec/avcodec.h”: No such file or directory

    在ffmpeg库下面的头文件包含时用"../"表示当前项目下的头文件就ok了

  5. linux上nginx上配置虚拟主机的相关配置

    1.配置主配置: nginx/conf/nginx.conf 2.虚拟主机配置:nginx/conf/extra/learn.weixin.com.conf 配置完后,重启服务器!

  6. 做游戏长知识------基于行为树与状态机的游戏AI(一)

    孙广东 2014.6.30 AI. 我们的第一印象可能是机器人,如今主要说在游戏中的应用. 现代的计算机游戏中已经大量融入了AI元素,平时我们进行游戏时产生的交互都是由AI来完毕的.比方在RPG游戏中 ...

  7. ubuntu设置中文拼音输入法

    转载  http://www.cnblogs.com/zhj5chengfeng/archive/2013/06/23/3150620.html

  8. 怎样用Javascript定义一个类

    其实Javascript中没有类这个定义,但是有类这个概念.很多人都写过这样的代码,对,没错,就是如下代码,清晰的不能再清晰了,就是一个关键字 function,然后定义一个方法名,方法名后紧跟一对括 ...

  9. NHibernate初学一之简单增删改查

    以前有简单了解NHibernate,但因项目一直没有运用所以也没有机会进行一个详细了解:最近利用一点空闲的时间认真学习它:同样希望把学习过程进行简单记录,今天简单写一个针对MSSQL数据库的增删改查的 ...

  10. string 线程安全

    线程安全:class Program { public delegate void MyDelegate(string aa); static void Main(string[] args) { M ...