当前位置: 首页 > news >正文

Servlet是线程安全的吗?

首先说明,Servlet是线程不安全的...
 
前两天,有个人问我“servlet是线程安全的吗?“,我却很难给出一个很具体清晰的回答,今天重新整理一下思路,也复习一下那些被扔回给老师的理论

servlet是线程安全的吗?NO

这个问题,在网上没有看到一个确切的答案,所以我们来分析一下:
首先什么是线程安全? 
引用概念:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

那么我们都知道servlet是多线程的,同时一个servlet实现类只会有一个实例对象,也就是它是Singleton的,所以多个线程是可能会访问同一个servlet实例对象的。

每个线程都会为数据实例对象开辟单独的引用,那么servlet会是线程安全的吗?

要判断是否是线程安全,我们需要知道线程安全问题是由什么引起的。
搜索得到答案:线程安全问题都是由全局变量及静态变量引起的。
看到这个答案,突然想起很多年前调查过的一个bug, 那时我们系统中遗留的代码中写了很多全局变量,有一次发布后,客户反馈,当有多人同时进行某个操作时,我们的数据出了问题,那时我们调查后的结果就是:多人同步操作时,有些全局变量的值不对了,之后我们专门设一个人花了很多工夫来将所有全局变量都改成了局部变量了,并且项目要求以后不允许用全局变量。原来那时侯我就已经碰到过线程不安全的情况了啊,不过处理方式或者不用全局,或者加入同步,若加入同步同时也要考虑一下对程序效率会不会产生影响。

由此可知,servlet是否线程安全是由它的实现来决定的,如果它内部的属性或方法会被多个线程改变,它就是线程不安全的,反之,就是线程安全的。

在网上找到一个例子,如下:

public class TestServlet extends HttpServlet {
     private int count = 0;  
      
     @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>"); 
         for(int i=0;i<5;i++){
             response.getWriter().println("count = " + count + "<BR>");
             try {
                 Thread.sleep(1000);  
                 count++;  
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }

  


当同时打开多个浏览器,输入http://localhost:8080/ServletTest/TestServlet时,他们显示的结果不同,这就说明了对于属性count来说,它是线程不安全的,
为了解决这个问题,将代码重构,如下:

public class TestServlet extends HttpServlet {
      private int count = 0;  
      private String synchronizeStr = ""; 
      @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>"); 
         synchronized (synchronizeStr){
             for(int i=0;i<5;i++){
                 response.getWriter().println("count = " + count + "<BR>");
                 try {
                     Thread.sleep(1000);  
                     count++;  
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }

  

 

相关文章:

  • 关于git rebase的相关讲解
  • Java 版本6下载大全
  • DNS 正向查找与反向查找
  • 拼音反查(转自大富翁)
  • 两只蚂蚁看见一只很大的梨
  • 将Button等控件嵌入到repeater中
  • #大学#套接字
  • 在线代码编译服务Codepad.org
  • OpenGL纹理映射
  • 微软与网景与浏览器之争
  • 《敏捷个人》周刊 第8期 (可下载)
  • Windows Azure HandBook (6) Azure带宽与Azure Blob云存储
  • 炼金术之真相
  • IE6下PNG32图片的透明
  • rowid结构浅析
  • “大数据应用场景”之隔壁老王(连载四)
  • 「面试题」如何实现一个圣杯布局?
  • co模块的前端实现
  • Debian下无root权限使用Python访问Oracle
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • Javascript Math对象和Date对象常用方法详解
  • JavaScript异步流程控制的前世今生
  • leetcode讲解--894. All Possible Full Binary Trees
  • Linux各目录及每个目录的详细介绍
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Redis 中的布隆过滤器
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 大数据与云计算学习:数据分析(二)
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 扑朔迷离的属性和特性【彻底弄清】
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 听说你叫Java(二)–Servlet请求
  • 微信小程序:实现悬浮返回和分享按钮
  • #QT项目实战(天气预报)
  • $.ajax,axios,fetch三种ajax请求的区别
  • (java)关于Thread的挂起和恢复
  • (javascript)再说document.body.scrollTop的使用问题
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (三)mysql_MYSQL(三)
  • (十八)SpringBoot之发送QQ邮件
  • .Net Remoting(分离服务程序实现) - Part.3
  • .net 按比例显示图片的缩略图
  • /var/spool/postfix/maildrop 下有大量文件
  • @entity 不限字节长度的类型_一文读懂Redis常见对象类型的底层数据结构
  • [2018][note]用于超快偏振开关和动态光束分裂的all-optical有源THz超表——
  • [C++] 多线程编程-thread::yield()-sleep_for()
  • [C++基础]-初识模板
  • [C和指针].(美)Kenneth.A.Reek(ED2000.COM)pdf
  • [Google Guava] 1.1-使用和避免null
  • [HAOI2016]食物链
  • [Kubernetes]2. k8s集群中部署基于nodejs golang的项目以及Pod、Deployment详解
  • [leetcode] 66. 加一
  • [LeetCode]284. Peeking Iterator(C++,类,暴力)
  • [poj 2001]Shortest Prefixes [Trie]