Servlet / JSP technology and ASP, PHP, etc. have high performance efficiency due to its multi-thread operation. Since servlet / jsp defaults is performed in multi-threaded mode, you need to consider multithreading synchronization issues very detailed when writing code. However, many people do not pay attention to multi-threaded synchronization when writing a servlet / jsp program, which often causes no problems in a small number of user access, and sometimes there are some values that have risen to a certain value. Ming Ming's problem is that the difficulty of debugging the problem of such randomness is also very large.
First, several variable types in servlet / JSP
When writing a servlet / jsp program, you must be careful to use the instance variable. Because instance variables are non-threaded. In Servlet / JSP, variables can be classified as the following categories:
Class variable
Request, Response, Session, Config, Application, and JSP page, Page, PageContext. In addition to Application, all other threads are safe.
2. Example variable
Example variables are all examples, allocated in the heap. In the Servlet / JSP container, only a servlet / jsp instance is generalized, starting a thread of the plurality of this instance to handle the request. The instance variable is shared by all threads of this example, so instance variables are not threads.
3. Local variables
The local variable is allocated in the stack because each thread has its own execution stack, so local variables are threads.
Second, multithreaded synchronization problem in servlet / jsp
In JSP, use instance variables should be particularly cautious. First see the following code:
// instanceconcurrenttest.jsp
<% @ page contenttype = "text / html; charset = GBK"%>
<%!
/ / Define instance variables
String username;
String password;
Java.io.printwriter output;
%>
<%
/ / Acquire parameters from Request
UserName = Request.getParameter ("UserName");
Password = Request.getParameter ("password");
Output = response.getwriter ();
Showuserinfo ();
%>
<%!
Public void showuserinfo () {
/ / In order to highlight the problem, first implement a fee at this time here.
INT i = 0;
Double Sum = 0.0;
While (i <200000000) {
SUM = I;
}
Output.println (thread.currentthread (). getname () "
");
Output.println ("UserName:" UserName "
");
Output.println ("Password:" Password "
);
}
%>
In this page, first define two instance variables, UserName, and Password. Then get these two parameters from the request, and call the showuserinfo () method to return the information requested to the customer's browser. There is no problem in one user access. However, when multiple users have access to access, information of other users will appear on other users' browsers. This is a serious problem. In order to highlight the problem, it is easy to test, observe, we have executed a simulated fee-hour operation when returning the user information, such as the following two users simultaneously access (can start two IE browser, or simultaneously on the two machines Access): A: http: // localhost: 8080 / instanceconcurrenttest.jsp? Usrname = a & password = 123
B: http: // localhost: 8080 / instanceconcurrenttest.jsp? username = b & password = 456
If a clicks, then then click the link, then A will return a blank screen, B get the output of the two threads of A and B. Please see the screenshot below:
Figure 1: A screen
Figure 2: B screen
As can be seen from the screenshot of the results, the web server launches two threads to handle requests from A and B, but get a blank screen in A. This is because Output, UserName, and Password in the above program are instance variables, which are shared all threads. After A Access this page, set the output of OUTPUT to A. The information is set to A. Set the information for B and point the output Output to B. When A thread is printed, it is printed to the screen of B, and the username and password of A are also replaced by B. Please take the following picture below:
Figure 3: Timeline of two threads of A, B
In the actual program, since the instance variable is set, the two time points of using the instance variable are very close, so the synchronization problem like this example is not so prominent, may occasionally appear, but this is more dangerous, it is more difficult to debugging.
Similarly, for the multi-threaded problem with instance variables, see the servlet version of the above page:
// instanceconcurrenttest.java
Import javax.servlet. *;
Import javax.servlet.http. *;
Import java.io.printwriter;
Public Class InstanceConcurrentTest Extends httpservlet
{
String username;
String password;
Printwriter out;
Public void doget (httpservletRequest Request,
Httpservletresponse response
THROWS servletexception, java.io.ioException
{
/ / Acquire parameters from Request
UserName = Request.getParameter ("UserName");
Password = Request.getParameter ("password");
System.out.println (thread.currentthread (). Getname () "| set username:" username);
OUT = response.getwriter ();
Showuserinfo ();
}
Public void showuserinfo () {
/ / In order to highlight the problem, first implement a fee at this time here.
INT i = 0;
Double Sum = 0.0;
While (i <200000000) {
SUM = I;
}
Out.println ("Thread:" thread.currentthread (). getname ());
Out.println ("UserName: UserName);
Out.println ("Password:" password;
}
}
Third, solution
1. Run servlet / JSP in a single thread
In JSP, by setting: <% @ page isthreadsafe = "false"%>, in the servlet, by implementing Javax.Servlet.singLethReadModel, the web container will ensure that the JSP or Servlet instance is running single-threaded manner.
Important: In the test, Tomcat 4.1.17 does not correctly support the iSthreadsafe property, so specifying the iStheadsafe to false, there is still a multi-thread problem in Tomcat 4.1.17, which is the bug of Tomcat 4.1.17. Tested in Tomcat 3.3.1 and RESIN 2.1.5.
2. Remove the instance variable, pass the parameters
From the above analysis, the use of instance variables should be avoided in servlet / JSP. For example, the following correction code removes the instance variable, by defining a local variable, and the parameter is transmitted. Thus, since the local variable is allocated in the stack of the thread, it is reasonable. There is no multithreaded synchronization problem. code show as below:
<% @ page contenttype = "text / html; charset = GBK"%>
<%
// use local variables
String username;
String password;
Java.io.printwriter output;
/ / Acquire parameters from Request
UserName = Request.getParameter ("UserName");
Password = Request.getParameter ("password");
Output = response.getwriter ();
ShowuserInfo (Output, UserName, Password);
%>
<%!
Public void showuserinfo (java.io.printwriter _output,
String _username, string _password) {
/ / In order to highlight the problem, first implement a fee at this time here.
INT i = 0;
Double Sum = 0.0;
While (i <200000000) {
SUM = I;
}
_output.println (thread.currentthread (). getname () "
"); _ output.println ("UserName: _Username "
");
_output.println ("Password:" _password "
");
}
%>
Note: Some information indicate synchronization using the Synchronized keyword on the related operation statement of the PrintuserInfo () method or instance variable, but this does not solve the multi-thread problem. Because, though can synchronize the operation code of the instance variable, it is not possible to prevent a thread from using another thread to modify "dirty" instance variables. Therefore, in addition to reducing operational efficiency, it will not play an expected effect.