Servlet Thread Safety issues

Source: Internet
Author: User
Tags volatile

The servlet runs on a single-instance multithreaded basis and is therefore not thread-safe . By default, non-distributed systems, the servlet container will only maintain an instance of a servlet, and when multiple requests reach the same servlet, the servlet container initiates multiple threads assigned to different requests to perform the service methods in the same servlet instance. Why did you do this? Effectively leverages the JVM's ability to allow multiple threads to access the same instance to improve server performance. Because either synchronizing a thread's call to the servlet, or initializing a servlet instance for each thread, presents a huge performance problem. This is why the servlet has a multithreaded security problem.

One servlet corresponds to multiple URL mappings, and multiple servlet instances will be generated. As shown below:

Output Result:

The output can see that the mappings /demoservlet1 and /demoservlet2 corresponding to the servlet instances are different.

The result is that the servlet will generate an instance for each URL map, and there may be multiple examples for a servlet, but each instance will have a different URL mapping.

One, the servlet handles multiple request access procedures

The servlet container defaults to handling multiple requests in a single-instance multithreaded manner.

1. When the Web server starts (or when the client sends a request to the server), the servlet is loaded and instantiated (there is only one servlet instance);

2, container initialization servlet is mainly read configuration files (such as Tomcat, can be set through the Servlet.xml <Connector> thread pool threads number, initialize the thread pools through Web. XML, initialize each parameter value and so on.

3. When the request arrives, the servlet container dispatches it through the dispatch thread (Dispatchaer thread) to manage the thread (worker thread) that is waiting to be executed in the threaded pool to the requestor;

4, the thread executes the Servlet service method;

5, the request is over, put back to the thread pool, waiting to be called; (note: Avoid using instance variables (member variables), because if a member variable exists, it may occur when multiple threads concurrently access the resource, to manipulate it, according to inconsistent data, resulting in thread safety issues)

As can be seen from the above:

First: The servlet single instance reduces the overhead of generating servlets;

Second: Through the line pool response to multiple requests, improve the response time of the request;

Third: The servlet container does not care whether the arriving Servlet requests access to the same servlet or another servlet, and assigns it directly to a new thread, and if it is multiple requests from the same servlet, Then the service method of the servlet will be executed concurrently in multi-threading;

IV: Each request is received by the ServletRequest object, which is requested by the Servletresponse object;

When the container receives a servlet request, the dispatcher thread selects a workgroup thread from the thread pool, passes the request to the thread, and then executes the servlet's service method by that thread. When this thread is executing, the container receives another request, and the dispatcher thread chooses another workgroup thread from the thread pool to service the new request, and the container does not care whether the request accesses the same servlet or another servlet. When a container receives multiple requests for the same servlet, the Servlet's service method executes concurrently on multiple threads.

Ii. designing a thread-safe servlet

The following is a discussion of several ways to ensure data thread synchronization in a single servlet and multithreaded scenario.

1, Synchronized: code block, method. Everyone will use the way, without detailed introduction. It is recommended that you first select the Adornment method.

2, volatile lightweight lock, you can ensure that the multi-threaded case of single-threaded reading of the modified variable will force to read the latest value from shared memory, but the assignment operation is not atomic.

A servlet demonstration with a simple count function:

   /**     * Use volatile as a lightweight lock as a counter     *      * @author yongboy     * @date 2011-3-12     * @version 1.0     */@ Webservlet ("/volatilecountdemo") public     class Volatilecountservlet extends HttpServlet {     private static Final long serialversionuid = 1L;          private volatile int num = 0;          protected void doget (HttpServletRequest request,     HttpServletResponse response) throws Servletexception, IOException {     addone ();     Response.getwriter (). Write ("Now access num:" + getnum ());     }          /**     * Read overhead low     *     /private int getnum () {     return num;     }          /**     * Its write is non-thread safe, the assignment operation overhead is high     *     /private synchronized void AddOne () {     num + +;     }     }     

When we assign a value to a volatile modifier, we still add the lock.

3, ThreadLocal can ensure that each thread can enjoy a copy of the variable, each thread can independently change the copy, does not affect other threads.

This assumes that a multithreaded environment can be a boring demonstration, initialize a count, and then loop the output:

 @WebServlet ("/threadlocalservlet") public class Threadlocalservlet extends HttpServlet {          Private static final long serialversionuid = 1L; private static ThreadLocal ThreadLocal = new ThreadLocal () {@Override protected Integer InitialValue () {Retu     RN 0;          }     };     protected void doget (HttpServletRequest request, httpservletresponse response) throws Servletexception, IOException {          Response.setheader ("Connection", "keep-alive");     PrintWriter out = Response.getwriter (); Out.println ("Start ...     "+" ["+ thread.currentthread () +"] ");          Out.flush ();     for (int i = 0; i <; i++) {out.println (Threadlocal.get ());          Out.flush ();     Threadlocal.set (Threadlocal.get () + 1);     }//manual cleanup, of course, with the current thread end, will also automatically clean up the Threadlocal.remove (); Out.println ("Finish ...     ");     Out.flush ();     Out.close (); }     } 

If you create an object that is expensive, but is not thread-safe, in some cases it requires only a separate change in the thread, without affecting other threads. Choose to use threadlocal better, well, also, its internal use of weakhashmap, weak references, the current thread ends, meaning that the copy of the object created will also be garbage collected. Hibernate creates a session using Threadlocal; Spring is also used to create objects that are used to a point.

Note that this is not the key to solving multi-threaded shared variables, even if you want a property or object to remain atomic in all threads, which is obviously not the solution.

4, lock Nothing to say, now the JDK version supports explicit lock, compared to synchronized, add and release more flexible, more comprehensive features.

@WebServlet ("/lockservlet") public     class Lockservlet extends HttpServlet {     private static final long Serialversionuid = 1L;          private static int num = 0;     Private static final Lock lock = new Reentrantlock ();          protected void doget (HttpServletRequest request, httpservletresponse response) throws Servletexception, IOException { c5/>try{     Lock.lock ();     num + +;     Response.getwriter (). println (num);     } finally{     Lock.unlock ();     }     }     

The lock must be released manually or it will remain locked.

5, wait/notify older thread thread synchronization scheme, compared to lock, is not recommended to use again.

6. Atomic Operation

An atomic wrapper class that includes wrappers for some basic types (int, long, double, Boolean, etc.), wrapper for object properties, and so on.

@WebServlet ("/atomicservlet") public     class Atomicservlet extends HttpServlet {     private static final long Serialversionuid = 1L;     private static final Atomicinteger num = new Atomicinteger (0);          protected void doget (HttpServletRequest request,     HttpServletResponse response) throws Servletexception, IOException {     PrintWriter out = Response.getwriter ();     Out.println (Num.incrementandget ());     Out.flush ();     Out.close ();     }     

The wrapper class provides a number of quick methods, such as the Incrementandget method above, which increases itself by 1, then returns the result value, and is thread-safe, saving us a lot of manual, clumsy coding implementations

7. Some suggestions

Try not to enable threads separately in the servlet;

Use local variables whenever possible;

Avoid using locks whenever possible;

the thread-safe property of the Servletcontext,httpsession,servletrequest object:

1. ServletContext: (thread insecure)

ServletContext is a multithreaded simultaneous read/write attribute, threads are unsafe. You want to synchronize the read and write properties or Deep Clone (). Therefore, in the context of the servlet, as little as possible to save the modified (write) data can be used in other ways to share in multiple servlets, for example, we can use a singleton mode to process the shared data.

2. HttpSession: (thread insecure)

The HttpSession object exists during a user session and can only be accessed in a thread that processes requests that belong to the same session, so the session object's property access is theoretically thread-safe.

When a user opens multiple browser windows that belong to a process, in which the access is in the same session, multiple requests are made and multiple worker threads are required to process the request, which can result in simultaneous multithreaded read and write properties. At this point we need to synchronize the reading and writing of the properties: using the synchronization block synchronized and using a read/write to resolve.

3. ServletRequest: (thread safe)

For each request, executed by a worker thread, a new ServletRequest object is created, so 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 and does not attempt to persist a reference to the request object after the service method ends.

Servlet Thread Safety issues

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.