zoukankan      html  css  js  c++  java
  • spring全局变量引起的并发问题

    先看下面小段代码,一个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正确时,可以确定不会出现并发问题。

  • 相关阅读:
    软件测试的定义及分类总结
    Selenium下拉菜单(Select)的操作Selenium快速入门(五)
    Selenium框架切换Selenium快速入门(七)
    元素(WebElement)Selenium快速入门(三)
    Selenium窗口切换Selenium快速入门(六)
    Selenium简介与环境搭配Selenium快速入门(一)
    测试用例的几种常见设计方法
    driver.get()和driver.navigate().to()到底有什么不同?Selenium快速入门(四)
    元素定位Selenium快速入门(二)
    关于VS2010与SQL Server2008 R2的安装问题
  • 原文地址:https://www.cnblogs.com/JAYIT/p/8431779.html
Copyright © 2011-2022 走看看