java全局变量引起的并发问题「建议收藏」

java全局变量引起的并发问题「建议收藏」最近刚完成了一个短彩信群发平台的开发工作,系统采用springmvc+hibernate+jdbctemplate+mysql架构。其中遇见许多问题,闲暇之余记录下来以避免在后续项目中再犯同样的错误。先看下面小段代码,一个controller,一个service。       controller.java代码:    ……..    @Autowired

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

最近刚完成了一个短彩信群发平台的开发工作,系统采用springmvc+hibernate+jdbctemplate+mysql架构。其中遇见许多问题,闲暇之余记录下来以避免在后续项目中再犯同样的错误。

先看下面小段代码,一个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配置文件那就直接加上scope=”prototype”就行啦

原文地址:http://my.oschina.net/robolin/blog/78395

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/171746.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • NGINX 实现端口转发

    NGINX 实现端口转发

    2021年11月23日
  • 让Web页面中的编辑器支持黏贴或直接拖拽来添加图片「建议收藏」

    让Web页面中的编辑器支持黏贴或直接拖拽来添加图片「建议收藏」让Web页面中的编辑器支持黏贴或直接拖拽来添加图片

  • 梦幻诛仙搭建教程_梦幻诛仙架设外网

    梦幻诛仙搭建教程_梦幻诛仙架设外网目前关于诛仙私服是否存在的争论还是在吵,但是我从网上找一一份诛仙私服架设教程,而且是比较傻瓜版的,新手也能看明白,发出来分享一下.本来准备自己架个自己玩的但看到SQL2005太大我的网速又慢就没装了等有机会搞来装装。如原著看到了别见怪我只是放这里自己留着看看。架设使用SQL数据库:SQLsever2005pro将服务器端解压缩到D:盘D:\Sagasevr下有6个文件夹1:databaseSQL…

  • moxa串口服务器网页版用户名密码,moxa串口服务器设置密码

    moxa串口服务器设置密码内容精选换一换登录Windows操作系统的弹性云服务器时,需使用密码方式登录。因此,用户需先根据创建弹性云服务器时使用的密钥文件,获取该弹性云服务器初始安装时系统生成的管理员密码(Administrator帐户或Cloudbase-init设置的帐户)。该密码为随机密码,安全性高,请放心使用。请根据您的个人需求,通过管理控制台或API方式获取Windo登录Windows…

  • Git 换行符检查 CRLF 与 LF

    Git 换行符检查 CRLF 与 LF

  • 读写TGA文件

    偶尔会遇到处理TGA文件的需求,封装成类以后再用到会很方便。    类的名字叫做myTGA,提供以下功能:    1:读取文件;    2:保存文件到指定目录;    3:获取图像信息(宽,高,深度/像素占用比特数,像素通道数);    4:访问像素;    5:转换到AUX_RGBImageRec 格式;    6:设计优良的结构易于扩展(目前只支

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号