Preface: There are a lot of basics about servlets, and this article is about threading security for Servlets.
1: Multithreaded servlet model
To understand the servlet thread safety, we must first know how the servlet instance is created and what its schema is.
By default, the servlet container creates only one servlet instance for the declared servlet, so if multiple clients request access to the Servlet,servlet container at the same time, multi-threading is taken. Now let's look at a picture
It can be seen that when a client sends a request, the servlet container selects a thread from the thread pool through the dispatcher thread, then passes the request to the thread, and then executes the servlet's service method from that thread.
If multiple clients request execution of a servlet instance at the same time, the service method of the Servlet container will execute concurrently on multiple threads (Figure 1, Customer 2, client 3 simultaneously invoke the Servlet1 instance, The dispatcher thread then calls the 3 threads in a thread pool for the customer's two-way request, and then 3 threads concurrently executes the service method of the Servlet1 instance, because the servlet container takes a single-instance multithreading method, This greatly reduces the overhead of servlet instance creation, increases the response time to requests, and thus causes the servlet thread safety problem. So we're talking about thread-safety issues.
2:servlet Thread Safety 2.1: Variable thread safety 2.1.1: Why is a variable thread-safe
Let's look at a piece of code first
1 Public classHelloworldservlet extends httpservlet{2 PrivateString UserName; 3 protected voiddoget (httpservletrequest request, httpservletresponse response) throws IOException4 {5Username=request.getparameter ("UserName");6PrintWriter out=Response.getwriter ();7 if(username!=NULL&&username!="")8 {9 out. Print (userName);Ten } One Else { A out. println ("user name does not exist"); - } - } the}
We analyze this code, there are now A,B2 client request Helloworldservlet This instance, servlet container allocation thread T1 to service a client request, T2 to service B client's request, the operating system first call T1 to run, T1 Run to the 6th line of time to get the user named Zhang San and save, when the time fragment, the operating system began to call T2 Run also run to the 6th row but this user name is John Doe, this time fragment again, the operating system began to run T1, starting from the 7th line, but the user name has become John Doe, When the output is really John Doe (obviously wrong), then there is a thread-safety issue.
2.1.2: How to prevent thread safety for variables
- Change the global variable to a local variable
protected voiddoget (httpservletrequest request, httpservletresponse response) throws IOException {String UserName=request.getparameter ("UserName"); PrintWriter out=Response.getwriter (); if(username!=NULL&&username!="") { out. Print (UserName); } Else { out. println ("user name does not exist"); } }
Because the username instantiation is overridden every time this method is called, there is no thread-safety issue.
- Synchronizing Doget with synchronized
protected synchronized void doget (HttpServletRequest request, httpservletresponse response)
The use of this method is obviously inappropriate, because such T2 must wait until the completion of T1 execution, and greatly affect the efficiency.
3. If it is a static resource then final indicates that the resource cannot be changed
Analogy final static String url= "Jdbc:mysql://localhost:3306/blog";
2.2: Thread Safety for attributes
Properties stored in the Servletcontext,httpsession,servletrequest object can be accessed in the servlet, and all three objects provide getattribute (), SetAttribute () method is used for fetching and setting properties, then the properties of these three different range objects are thread-safe, let's take a look
2.2.1:servletcontext
The first thing to make clear is that ServletContext is shared by all Servlets under the application, then the ServletContext object can be accessed by all servlets of the Web application. Then multiple servlets can set and access the ServletContext properties at the same time, so there is a thread-safety problem. Let's take a look at the code
1 protected voidService (HttpServletRequest request, httpservletresponse response)2 {3String username=request.getparameter ("UserName");4 if("Login") {5List list= (list) Getservletcontext (). getattribute ("UserList");6 List.add (userName);7 }8 Else {9List list= (list) Getservletcontext (). getattribute ("UserList");Ten List.remove (userName); One } A}
1 protected voidService (HttpServletRequest request, httpservletresponse response)throwsIOException2 {3List list= (list) Getservletcontext (). getattribute ("UserList");4 intCount=list.size ();5 for(inti=0;i<count;i++)6 {7PrintWriter out=Response.getwriter ();8 out.println (List.get (i));9 }Ten}
The first code is when the user logs in after the user name is saved in the ServletContext attribute, if not logged on to delete the user
The second piece of code is to see all the user logins for the application, so we'll see how the thread-safety problem occurs.
When 2 requests execute concurrently, the second piece of code may have just executed the fifth line of time to obtain the count=5; but another request happens to execute the first line of code tenth, delete one of the users, and when the second piece of code runs through the loop to count= When you are 5, the array exceeds the straight line. Then there is a thread-safety issue at this point. So how to solve this problem, the first is to save the ServletContext attribute value, the second is to use synchronized synchronization (this low efficiency)
2.2.2:httpsession
The HttpSession object survives during a user session and is not shared by all users like ServletContext, so a httpsession is requested only by one user at a time, so the theory seems to be thread-safe, In fact, this is not the case, this is related to the browser, in the previous session we said that the same browser can only have one session, then this will be a session thread security problem, see the following code
1 protected voidService (HttpServletRequest request, httpservletresponse response)throwsIOException2 {3String commandtype=request.getparameter ("CommandType");4HttpSession session=request.getsession ();5List list= (list) Session.getattribute ("Items");6 if("Add". Equals (CommandType)) {7 //Add8 }9 Else if("Delete". Equals (CommandType)) {Ten //Delete One } A Else { - intCount=list.size (); - for(inti = 0; I < count; i++) { the //Traverse - } - } -}
The above is a simple pseudo-code to add the item information, if the user now in a browser window to delete an item while in another window to get all the items this time will appear thread safety, from the above introduction to know that the servlet container is a single instance of multithreading, At this point the servlet container allocates 2 threads to service the deletion of items and get all items, if one of the threads just runs to the end of a 14-line time fragment, and another thread runs line 10th to delete an item information, and then the first thread starts to run the 15th start traversal, At this point there is also an error that the above array simply goes out of scope.
2.2.3:httprequest
HttpRequest is thread-safe because each request invokes the service, creating a new HttpRequest and local variables.
3:singlethreadmodel
Well understood from the name, is the single-threaded mode, that is, if the servlet implements the Singlethreadmodel interface, The servlet container guarantees that only one thread at a time is running on the service method of the servlet instance (in fact, it is almost synchronous), which is very inefficient, and now Singlethreadmodel has been discarded. It is important to note that even if the servlet implements the Singlethreadmodel interface does not necessarily guarantee thread safety, metaphorically speaking servletcontext,httpsession, because ServletContext is an application-shared, It is possible that 2 servlet instances are running concurrently, resulting in thread safety, and httpsession because they are shared in the same browser (although the odds are small)
4: summary
1: As long as we understand the schema of the servlet container work, it may be possible to understand why the servlet is a thread-safe issue, so be sure to keep in mind that the servlet container is a multithreaded single-instance model
2: Avoid using global variables, it is better to use local variables, in fact, this is a good programming habit in itself
3: Read-only instance variables and static variables should be used (that is, the previous plus final meaning immutable)
4: Do not create a thread on the servlet itself, because the servlet container has done it for us.
5: If you want to modify the shared object, remember to synchronize, as far as possible to narrow the range of synchronization (analogy to modify the session directly using synchronized), to avoid affecting performance
Javaweb Review of the sixth chapter on servlet thread safety