Servlet总结04——注意Servlet单实例的线程安全性

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

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



(一)变量的安全性

错误实例:

public class test extends HttpServlet{

  String user = "" ;

  public void doGet(HttpServletRequest req , HttpServletResponse res) throws ServletException , IOException{
    user = req.getParameter("user");
    ......
  }

}

  例如: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的“请求”将串行处理,影响效率。






原文地址:https://www.cnblogs.com/huangfox/p/2220466.html