• Spring MVC 线程安全问题的思考


    Spring MVC 线程安全问题的思考

    在读一些博文的时候发现有些文章对SpringMVC的Controller线程安全的验证并不正确,比如没有探究controller线程不安全的具体原因,比如将请求线程当做controller多例的证明,以下将验证。
    http://bbs.csdn.net/topics/390894585
    http://bbs.csdn.net/topics/390891861#post-398241838
    

    1.request请求线程与controllte的关系是什么?

    简易的验证方法代码

    在网上随便下载了一个压力测试工具

    测试结果如下

    从打印的日志可以看出,请求时多线程请求的,但是每次请求过来调用的Controller对象都是一个,而不是一个请求过来就创建一个controller对象

    那为什么说controller是不安全的呢?

    原因就在于如果这个controller对象是单例的,那么如果不小心在类中定义了类变量,那么这个类变量是被所有请求共享的,这可能会造成多个请求修改该变量的值,出现与预期结果不符合的异常。

    接下来将验证多并发的情况下controller的线程不安全的具体表现、通过配置实现controller多例

    在单例的情况下 相当于所有类变量对于每次请求都是共享的,每一次请求对类变量的修改都是有效的

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. private static int st=0;  
    2. private int index=0;  
    3. @RequestMapping(value="/testcontrollersinglon",method=RequestMethod.GET)  
    4.     @ResponseBody  
    5.     public String testControllerSinglon(HttpServletRequest request){  
    6.         try {  
    7.             System.out.println(st++ + " | " + index++);  
    8.             return "yes";  
    9.         } catch (Exception e) {  
    10.             e.printStackTrace();  
    11.             return "error";  
    12.         }  
    13.     }  

    看一下打印的日志


    通过日志可以看出 变量index为所有请求共享 

    那有没有办法让controller不以单例而以每次请求都重新创建的形式存在呢?

    答案是当然可以,只需要在类上添加注解@Scope("prototype")即可,这样每次请求调用的类都是重新生成的(每次生成会影响效率)

    添加@Scope("prototype")后我们再看看日志就会看出区别了

    虽然这样可以解决问题,但增加了时间成本,总让人不爽,还有其他方法么?答案是肯定的!使用ThreadLocal 来保存类变量,将类变量保存在线程的变量域中,让不同的请求隔离开来

  • 相关阅读:
    posix多线程有感POSIX 线程间的内存可视性
    同步和互斥的一些问题(死锁,优先级逆转)
    POSIX线程属性
    POSIX 条件变量详细解析
    VMware网络配置详解
    POSIX线程
    Java+Selenium——Actions鼠标悬停
    Java+Selenium——截图方法TakeScreenshot——保存到桌面——TakeScreenshot截图只针对浏览器的web事件
    Java+Selenium——利用Robot类截图——整个桌面截图
    Java+Selenium——如何处理日历控件——方法二
  • 原文地址:https://www.cnblogs.com/handsome1013/p/6182816.html
Copyright © 2020-2023  润新知