In-depth research on servlet multi-thread security

Source: Internet
Author: User

Abstract: This article introduces the servlet multithreading mechanism. It uses an instance and the Java memory model to explain the cause of servlet thread insecurity and provides three solutions to ensure servlet thread security, it also describes the trade-off between the three solutions in actual development.

  Keywords: Servlet thread Security synchronization Java Memory Model instance variables

Compared with ASP and PHP, Servlet/jsp has a high execution efficiency due to its multi-threaded operation. Servlet/JSP is executed in multi-thread mode by default. Therefore, you must carefully consider the security of multiple threads when writing code. However, many developers have not noticed the multi-thread security issue when writing Servlet/jsp programs, which often causes no problems when a few users access the program, when the number of concurrent users reaches a certain value, some unknown problems often occur.

  Multi-thread mechanism of Servlet
 
The servlet architecture is built on the Java multithreading mechanism, and its lifecycle is the responsibility of Web containers. When the client requests a servlet for the first time, the servlet container will instantiate the servlet class according to the Web. xml configuration file. When a new client requests the servlet, the servlet class is generally not instantiated, that is, multiple threads are using this instance. Servlet containers automatically Use thread pools and other technologies to support system running, as shown in figure 1.


Figure 1 servlet Thread Pool

In this way, when two or more threads access the same servlet at the same time, multiple threads may access the same resource at the same time, and the data may become inconsistent. Therefore, if you do not pay attention to thread security issues when using Servlet to build Web applications, the servlet program will be hard to find errors.

  Servlet thread security issues

Servlet thread security problems are mainly caused by improper use of instance variables. Here is a realistic example.

Import javax. servlet .*;
Import javax. servlet. http .*;
Import java. Io .*;
Public class Concurrent Test extends httpservlet {printwriter output;
Public void Service (httpservletrequest request,
Httpservletresponse response) throws servletexception, ioexception {string username;
Response. setcontenttype ("text/html; charset = gb2312 ");
Username = request. getparameter ("username ");
Output = response. getwriter ();
Try {thread. Sleep (5000); // to highlight concurrency issues, set a latency here
} Catch (interrupted exception e ){}
Output. println ("username:" + username + "<br> ");
}
}

The servlet defines an instance variable output, which is assigned to the user output in the service method. When a user accesses the servlet, the program runs normally, but when multiple users access the servlet concurrently, the information of other users may be displayed on the browsers of other users. This is a serious problem. To highlight concurrency issues and facilitate testing and observation, we performed a delayed operation when returning user information. Assume that. the servlet is registered in the XML configuration file. Currently, two users a and B can access the servlet at the same time (two ie browsers can be started or accessed simultaneously on both machines ), enter:

A: http: // localhost: 8080/servlet/concurrenttest? Username =

B: http: // localhost: 8080/servlet/concurrenttest? Username = B

If user B is a little slower than user a's carriage return time, output 2 is displayed:


Figure 2 browser output of user a and user B

As shown in figure 2, the web server starts two threads to process requests from user a and user B respectively, but a blank screen is displayed on user a's browser, user A's information is displayed on user B's browser. The servlet has thread insecurity issues. Next we will start with analyzing the memory model of the instance and observe the output value of the instance variable at different times to analyze the cause of the servlet thread being unsafe.

The Java Memory Model jmm (Java Memory Model) jmm defines the relationship between threads and memory. According to the jmm design, the system has a main memory (main memory). All instance variables in Java are stored in the main memory, and all threads are shared. Each thread has its own working memory. The working memory is composed of two parts: the cache and the stack. The cache stores copies of variables in the main memory, the cache may not always synchronize the primary memory, that is, the modifications to the variables in the cache may not be immediately written to the primary memory; the stack stores the local variables of the thread, threads cannot directly access the variables in the stack. Based on jmm, We can abstract the memory model of the servlet instance discussed in this paper into the model shown in figure 3.


Figure 3 jmm model of the servlet instance

The following uses the memory model shown in Figure 3 to analyze the concurrent execution of user a and user B threads (for short, thread a and thread B, variable changes and thread execution in the servlet instance, as shown in figure 4.

Scheduling time Thread Line B
T1 Access the servlet page  
T2   Access the servlet page
T3 Output = username of output = a sleep for 5000 milliseconds, giving way to the CPU  
T4   Output = B's output (written back to the primary storage) username = B sleep for 5000 milliseconds, giving the CPU
T5 Output the username value of thread a in user B's browser, and thread a terminates.  
T6   Output the username value of line B in user B's browser, and line B is terminated.

Figure 4 servlet instance Thread Scheduling

From figure 4, we can clearly see that the modification of thread B to the instance variable output overwrites the modification of thread a to the instance variable output, as a result, user a's information is displayed on user B's browser. If, when thread a executes the output statement, the changes made by thread B to the output are not refreshed to the primary storage, the output result shown in Figure 2 is not displayed. Therefore, this is just an accidental phenomenon, but this increases the potential risks of the program.

 

Design a thread-safe Servlet

Through the above analysis, we know that incorrect use of instance variables is the main cause of servlet thread insecurity. The following three solutions are provided for this problem and some reference suggestions are provided for the selection of solutions.

1. Implement the singlethreadmodel Interface

This interface specifies how the system handles calls to the same servlet. If a servlet is specified by this interface, no two threads will be executed simultaneously in the service method of this servlet. Of course, there is no thread security problem. In this method, you only need to change the Class header definition of the previous concurrent test class:

Public class Concurrent Test extends httpservlet implements singlethreadmodel {
............
}

2. Synchronize operations on shared data

The synchronized keyword ensures that only one thread can access the protected segment at a time. In this paper, the servlet can guarantee thread security through synchronous block operations. The code after synchronization is as follows:

............
Public class Concurrent Test extends httpservlet {............
Username = request. getparameter ("username ");
Synchronized (this ){
Output = response. getwriter ();
Try {
Thread. Sleep (5000 );
} Catch (interrupted exception e ){}
Output. println ("username:" + username + "<br> ");
}
}
}

3. Avoid using instance variables

Thread security issues in this instance are caused by instance variables. As long as instance variables are not used in any method in the servlet, the servlet is thread-safe.

Modify the servlet code above and change the instance variable to a local variable to implement the same function. The Code is as follows:

......
Public class Concurrent Test extends httpservlet {public void Service (httpservletrequest request, httpservletresponse
Response) throws servletexception, ioexception {
Print Writer output;
String username;
Response. setcontenttype ("text/html; charset = gb2312 ");
......
}
}

The above three methods can be tested to show that all of them can be used to design thread-safe servlet programs. However, if a servlet implements the singlethreadmodel interface, the servlet engine will create a separate servlet instance for each new request, which will cause a large amount of system overhead. Singlethreadmodel is no longer recommended in servlet2.4. If synchronization is used in a program to protect the shared data to be used, the system performance will be greatly reduced. This is because the synchronized code block can only be executed by one thread at a time, reducing the throughput for simultaneously processing customer requests and blocking many customers. In addition, to ensure data consistency between the main memory and the working memory of the thread, the cache should be refreshed frequently, which will greatly affect the system performance. Therefore, in actual development, we should also avoid or minimize the synchronization code in the servlet; In serlet, avoiding using instance variables is the best choice to ensure servlet thread security. We can also know from the Java memory model that the temporary variables in the method allocate space on the stack, and each thread has its own private stack space, so they do not affect thread security.

  Summary

Servlet thread security issues are only apparent when a large number of concurrent accesses are made, and are difficult to find. Therefore, pay special attention to this issue when writing servlet programs. Thread security problems are mainly caused by instance variables. Therefore, you should avoid using instance variables in servlet. If the application is designed to avoid using instance variables, use synchronization to protect the instance variables to be used. To ensure the optimal performance of the system, the code path with the minimum availability should be synchronized.

2. How to develop a thread-safe Servlet

The action in struts is the same as the servlet mechanism, and there is a multi-thread security problem. The same solution. It is best to replace the instance variable with a local variable (so there is no sharing problem), and then try to narrow down the scope of the synchronization code block.
1. Variable Thread security: the variables here refer to fields and shared data (such as form parameter values ).

A. localize the parameter variables. Multithreading does not share local variables, so we should try to use local variables in servlet.
Example: String user = "";
User = request. getparameter ("user ");

B. Use the synchronous block synchronized to prevent code blocks that may be called asynchronously. This means that the thread needs to be queued for processing.
When using the same section, we should try to narrow the scope of the synchronization code as much as possible. Do not use synchronization directly in the sevice method and response method, which will seriously affect the performance.

2. Attribute thread security: attributes in the servletcontext, httpsession, and servletrequest objects
Servletcontext: (the thread is insecure)
Servletcontext can read/write attributes in multiple threads at the same time, and the thread is not secure. You need to synchronize read/write operations on attributes or perform in-depth clone ().
Therefore, in the servlet context, try to save as little data as possible that will be modified (written). You can use other methods to share data among multiple servlets. For example, you can use the singleton mode to process shared data.
Httpsession: (the thread is insecure)
Httpsession objects exist during user sessions and can only be accessed in the thread that processes requests from the same session. Therefore, attribute access to session objects is theoretically thread-safe.
When you open multiple browser windows of the same process and access to these windows belongs to the same session, multiple requests are sent, and multiple worker threads are required to process the requests, it may cause simultaneous multi-threaded read/write attributes.
In this case, we need to synchronize the read and write of the attribute: Use the synchronization block synchronized and the read/write tool.

Servletrequest: (the thread is secure)
Each request is executed by a worker thread and a new servletrequest object is created. Therefore, the servletrequest object can only be accessed in one thread. Servletrequest is thread-safe.
Note: The servletrequest object is valid within the scope of the service method. Do not try to save the reference of the request object after the service method ends.

3. Use the synchronous collection class:
Use Vector instead of arraylist, and use hashtable instead of hashmap.

4. Do not create your own thread in the servlet to complete a function.
The servlet itself is multi-threaded. re-creating a thread in the servlet will complicate the execution and cause multi-threaded security issues.

5. You must lock external objects (such as files) in multiple servlets for mutually exclusive access.

6. javax. servlet. the singlethreadmodel interface is an identifier interface. If a servlet implements this interface, the servlet container ensures that only one thread can be executed in the service method of the given servlet instance at a time point. All other requests are queued.
The server can use multiple instances to process requests, replacing the benefits of queuing requests for a single instance. The server creates an instance pool composed of multiple servlet instances of the servlet class. The server allocates the servlet instance for Response Processing for each request, and then places it back in the instance pool to wait for this request. In this way, concurrent access is caused.
At this time, local variables (fields) are secure, but global variables and shared data are insecure and need to be synchronized. In this case, the singlethreadmodel interface cannot solve the concurrent access problem.

The singlethreadmodel interface has been deprecated In the servlet specification.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.