一、问题

对于实例变量来说,由于servlet在Tomcat中是以单例模式存在的,所有的线程共享实例变量。多个线程对共享资源的访问造成了线程不安全问题。
案例如下:

  1. import java.io.IOException;
  2. import java.io.PrintWriter;
  3. import javax.servlet.http.HttpServlet;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. public class HelloWorldServlet extends HttpServlet
  7. {
  8. String message;
  9. /**
  10. *
  11. */
  12. private static final long serialVersionUID = 787553024399133588L;
  13. public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
  14. message =request.getParameter("message");
  15. PrintWriter pw = response.getWriter();
  16. try
  17. {
  18. Thread.sleep(5000);
  19. }
  20. catch (InterruptedException e)
  21. {
  22. e.printStackTrace();
  23. }
  24. pw.write("<div><strong>Hello World</strong>!</div>"+message);
  25. pw.close();
  26. }
  27. }

在构建好的工程部署到本地Tomcat下,启动Tomcat,打开俩个浏览器
访问1: http://localhost:8080/Servlet03/HelloWorld?message=helloA
访问2: http://localhost:8080/Servlet03/HelloWorld?message=helloB

分别刷新访问,在访问第一个地址的页面打印出了helloB,在访问第二个地址的时候页面有时候会打印出helloA。这个就是高并发下的多线程的安全问题。

二、解决方式:

  • 添加同步代码锁 synchronized
  • 将要访问的实例变量改为局部变量多线程下每个线程对局部变量都会有自己的一份copy,这样对局部变量的修改只会影响到自己的copy而不会对别的线程产生影响,线程安全的

三、补充

struts1 因为是基于servlet开发的框架,存在安全隐患。所以才催生来后来的struts2(基于filter,摆脱了线程安全问题),但技术上二者并无多少联系,分别属于两个开发团队。


资料参考: https://www.cnblogs.com/alaskan/p/4178533.html