How do you make a Servlet thread safe? What do you need to be concerned about with storing data in Servlet instance fields?

As shown in the figure Servlet Life Cycle in this article, a typical (or default) Servlet life cycle creates a single instance of each servlet and creates multiple threads to handle the service() method. The multithreading aids efficiency but the servlet code must be coded in a thread-safe manner. The shared resources (e.g. instance variables, utility or helper objects etc) should be appropriately synchronized or should only use variables in a read-only manner. There are situations where synchronizing will not give you the expected results as shown in the diagram below and to achieve the expected results you should store your values in a user session or store them as hidden field values. Having large chunks of code in synchronized blocks in your service or doPost() methods can adversely affect performance and makes the code more complex. Consider the following servlet code:

public class MyServlet extends HttpServlet {

    //immutable, so thread safe
    private static final int CONSTANT = 5; 

    //mutable instance variable    
    private int x = 0; // not thread safe

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {

        ServletOutputStream out = resp.getOutputStream();

        // local variable y        
        int y = new Integer(request.getParameter("suppliedValue")).intValue();

        incrementValue(y); // Line A
        out.println("<html><h1>Output to Browser</h1>"); // Line B        
        out.println("<body>X= " + getX() + "<body></html>"); // Line C   
    }

    private void incrementValue(int value) {
        x = x + value + CONSTANT;
    }

    private void getX() {
        return x;
    }
}

Note: As shown above, the methods doPost()incrementValue() and getX()  are executed in the stack memory and will have its own copy of local variable “y”. But the member variable “x”  and immutable constant “CONSTANT” are stored in the heap memory. The heap memory is shared by all the threads and hence the variable “x” is not thread-safe and variable “CONSTANT” is thread-safe because it is immutable (i.e read-only, cannot be modified).

Why the variable “x” is not thread-safe? Say the user-1 submits a request with a “suppliedValue” parameter 1 and expects returned a value of 6 (i.e. x + value + CONSTANT =  0 + 1 + 5).  The user-2 submits a request with a “suppliedValue” parameter 2 and expects a returned value of 7 (i.e. 2 + value + CONSTANT =  0 + 2 + 5). If thread-1 from user-1 has executed “Line A” which has incremented the value of “x” to 6 and moves to “Line B”. While client 1 is in “Line B” the thread-2 from user-2 is executing the “Line A” whereby modifying the value of x to 13 (i.e. x + value + CONSTANT =  6 + 2 + 5) . Now, when the thread-1 from user-1 executes the “Line C”, it reads the value of “x” incorrectly as 13 (instead of 6) because the thread-2 from client 2 has modified the value. Even the thread-2 from client 2 reads the incorrect value of 13 (instead of 7).  Also, there are other possibilities such as if thread-2 wins the race by executing the “Line A” first then the user-2 may get the value of either 7 and the user-1 may get the value of 13.

How to prevent this?  In this scenario synchronizing the methods would not also help. You need to store the value “x” for each user separately. The above thread-safety issue can be prevented by storing the variable “x” in a session or as a hidden field where each user will have his/her own copy of the value for “x” as opposed to sharing the same value from the heap memory. If you just need a cumulative value for each user like say user-1 gets the value of 6 (i.e 0 + 1 + 5) and the user-2 gets the value of 13 (i.e. 6 + 2 + 5) or vice-versa i.e user-2 gets the value of 7 and the user-1 gets the value 13, this can be achieved by slightly modifying the program by removing getX() method and changing the incrementValue(int value) method  and modifying the doPost() methods as shown below: 

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
    … //skipping lines           
    int y = new Integer(request.getParameter("suppliedValue")).intValue();
    // Line A -> accessed in a thread safe manner and stored in a local variable “w”. Each           
    // user will have his own copy of “w” 
    int w = incrementValue(y);
    out.println("<html><h1>Output to Browser</h1>"); // Line B           
    out.println("<body>X= " + w + "<body></html>"); // Line C           
    … //skipping lines   
}

//since synchronized, only one thread can access at a time    
private synchronized int incrementValue(int value) {
    x = x + value + IMMUTABLE_CONSTANT;
    return x;
}

Best practice: It is best practice to use multi-threading and stay away from the single-threaded model of the servlet unless otherwise there is a compelling reason for it. Shared resources can be synchronized, used in a read-only manner, or shared values can be stored in a session, as hidden fields or in the database table. The single-threaded model can adversely affect performance and hence has been deprecated in the servlet specification 2.4. As shown in the diagram above, threads share the heap and have their own stack space (i.e. each thread has its own stack). This is how one thread’s invocation of a method (doGet(), doPost()) and its local variables (e.g. int y ) are kept thread-safe from other threads. But the heap (e.g. int x ) is not thread-safe and must be synchronized for thread safety or stored in an HTTP session or stored as a hidden field. The variable “CONSTANT” is a read-only immutable field since it is marked as final and hence thread-safe.   

J2EE Core Java Servlet