Servlet及JSP中的多线程同步问题

你并不懂我1258

你并不懂我1258

2016-01-29 12:13

Servlet及JSP中的多线程同步问题,Servlet及JSP中的多线程同步问题
    Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的同步问题。然而,很多人编写Servlet/JSP程序时并没有注意到多线程同步的问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫明其妙的问题,对于这类随机性的问题调试难度也很大。

  一、在Servlet/JSP中的几种变量类型

  在编写Servlet/JSP程序时,对实例变量一定要小心使用。因为实例变量是非线程安全的。在Servlet/JSP中,变量可以归为下面的几类:

  1. 类变量

  request,response,session,config,application,以及JSP页面内置的page, pageContext。其中除了application外,其它都是线程安全的。

  2. 实例变量

  实例变量是实例所有的,在堆中分配。在Servlet/JSP容器中,一般仅实例化一个Servlet/JSP实例,启动多个该实例的线程来处理请求。而实例变量是该实例所有的线程所共享,所以,实例变量不是线程安全的。

  3. 局部变量

  局部变量在堆栈中分配,因为每一个线程有自己的执行堆栈,所以,局部变量是线程安全的。

  二、在Servlet/JSP中的多线程同步问题

  在JSP中,使用实例变量要特别谨慎。首先请看下面的代码:

// instanceconcurrenttest.jsp<%@ page contentType="text/html;charset=GBK" %<%!     //定义实例变量     String username;     String password;    java.io.PrintWriter output;%<%     //从request中获取参数    username = request.getParameter("username");    password = request.getParameter("password");    output = response.getWriter();    showUserInfo();  % <%!     public void showUserInfo() {         //为了突出并发问题,在这儿首先执行一个费时操作         int i =0;         double sum = 0.0;         while (i++ < 200000000) {             sum += i;         }                  output.println(Thread.currentThread().getName() + "<br");       output.println("username:" + username + "<br");        output.println("password:" + password + "<br");     } %


  在这个页面中,首先定义了两个实例变量,username和password。然后在从request中获取这两个参数,并调用showUserInfo()方法将请求用户的信息回显在该客户的浏览器上。在一个用户访问是,不存在问题。但在多个用户并发访问时,就会出现其它用户的信息显示在另外一些用户的浏览器上的问题。这是一个严重的问题。为了突出并发问题,便于测试、观察,我们在回显用户信息时执行了一个模拟的费时操作,比如,下面的两个用户同时访问(可以启动两个IE浏览器,或者在两台机器上同时访问):

a: http://localhost:8080/instanceconcurrenttest.jsp?username=a&password=123

b: http://localhost:8080/instanceconcurrenttest.jsp?username=b&password=456

如果a点击链接后,b再点击链接,那么,a将返回一个空白屏幕,b则得到a以及b两个线程的输出。请看下面的屏幕截图:



图1:a的屏幕




图2:b的屏幕


  从运行结果的截图上可以看到,Web服务器启动了两个线程分别来处理来自a和b的请求,但是在a却得到一个空白的屏幕。这是因为上面程序中的output, username和password都是实例变量,是所有线程共享的。在a访问该页面后,将output设置为a的输出,username,password分别置为a的信息,而在a执行printUserInfo()输出username和password信息前,b又访问了该页面,把username和password置为了b的信息,并把输出output指向到了b。随后a的线程打印时,就打印到了b的屏幕了,并且,a的用户名和密码也被b的取代。请参加下图所示:



图3:a、b两个线程的时间线


  而实际程序中,由于设置实例变量,使用实例变量这两个时间点非常接近,所以,像本例的同步问题并没有这么突出,可能会偶尔出现,但这却更加
展开更多 50%)
分享

猜你喜欢

Servlet及JSP中的多线程同步问题

Java JAVA基础
Servlet及JSP中的多线程同步问题

关于Servlet及JSP中遇到的多线程同步问题

编程语言 网络编程
关于Servlet及JSP中遇到的多线程同步问题

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Delphi中实现多线程同步查询(2)

Delphi
Delphi中实现多线程同步查询(2)

Delphi中实现多线程同步查询(1)

Delphi
Delphi中实现多线程同步查询(1)

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Swing中的多线程

编程语言 网络编程
Swing中的多线程

Java 程序中的多线程

编程语言 网络编程
Java 程序中的多线程

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Flash AS3.0菜鸟学飞教程:间隔循环的三种表现方式

Flash AS3.0菜鸟学飞教程:间隔循环的三种表现方式

实现文件加密功能

实现文件加密功能
下拉加载更多内容 ↓