厚积薄发

不忘初心,方得始终!

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

注意Servlet单实例的线程安全性

Servlet容器采用了单实例多线程的方式(Servlet容器默认的设置),这样可以减少创建实例的开销,提高效率。

但是在多线程方面也埋下了不少隐患,需要开发者格外小心。



变量的安全性

错误实例:

 1 public class test extends HttpServlet{
 2  
 3   String user = "" ;
 4  
 5   public void doGet(HttpServletRequest req , HttpServletResponse res) throws ServletException , IOException{
 6     user = req.getParameter("user");
 7     ......
 8   }
 9  
10 }

例如:a、b同时访问这个servlet,a提交的user=aaa,b提交的user=bbb。

首先,servlet容器分配一个线程T-a来处理请求a,获取其user的值aaa,并赋给变量user。此时T-a时间片到了,servlet容器分配另外一个线程T-b来处理请求b,

获取其user的值bbb,并覆盖变量user,当T-a线程重新获取执行权时,user已经“物是人非”了。

这里可以类比:jdbc的事务管理,“丢失更新”和这个场景类似。
 

解决方案

1)定义本地变量,将user在doGet方法中定义。

因为user是本地变量,每一个线程都有user变量的拷贝,彼此不受影响。
 

2)设置方法同步(或者同步块)

因为设置了同步,可以防止多个线程同时调用doGet方法。但是所有请求该servlet的“请求”将串行处理,影响效率。

posted on 2016-07-04 11:49  欢迎来到Java的世界  阅读(121)  评论(0)    收藏  举报