Write thread-safe servlets

Learn how to handle thread safety

1 2 Page 2
Page 2 of 2
package threadSafety;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import java.math.*;
public class SimpleServlet extends HttpServlet
{
  //A variable that is NOT thread-safe!
  private int counter = 0;
  private String mutex = "";
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
  {
    doPost(req, resp);
  }
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
  {
    resp.getWriter().println("<HTML><BODY>");
    resp.getWriter().println(this + ": <br>");
    synchronized (mutex)
    {    
      for (int c = 0; c < 10; c++)
      {
        resp.getWriter().println("Counter = " + counter + "<BR>");
        try
          {
          Thread.currentThread().sleep((long) Math.random() * 1000);
          counter++;
        }
        catch (InterruptedException exc) { }
      }
    }
    resp.getWriter().println("</BODY></HTML>");
  }
}

Notice how the synchronized code block begins where we first begin to access the variable and ends when we are done with it. You must either synchronize an entire method or use an object. In our example, I created a string that is an instance variable. This string is called a mutex (short for mutual exclusion) and is shared among all threads, thus ensuring that only one thread has access to the specified code block at any time.

In our simple example, the synchronization block is small. If it weren't small, we would want to carefully analyze the logic and possibly refactor the code such that anything that can be done asynchronously is not within the synchronized block. In the Web world, predicting your largest load is not always easy, and when introducing a synchronized code block, every millisecond counts.

In the event you find yourself with more synchronized code than nonsynchronized code and your estimated load is minimal, you have yet another choice. Simply put, just tell the servlet container your servlet is not thread-safe.

Your last defense: Whole synchronization

To tell the servlet container your thread is not thread-safe, implement an empty interface. Empty interfaces are used as tags, so other classes can check for the interface and act accordingly. The tag we want to implement is the javax.servlet.SingleThreadModel interface. The servlet container specification states that if your servlet implements this interface, you will be guaranteed that no two threads will simultaneously execute your servlet's service() method. Remember, service() is the underlining implementation for both the doGet() and doPost() methods, so we're safe. The following code snippet illustrates this interface's usage:

package threadSafety;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import java.math.*;
public class SimpleServlet extends HttpServlet implements SingleThreadModel
{
  //A variable that is NOT thread-safe!
  private int counter = 0;
  public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
  {
    doPost(req, resp);
  }
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
  {
    resp.getWriter().println("<HTML><BODY>");
    resp.getWriter().println(this + ": <br>");
    for (int c = 0; c < 10; c++)
    {
      resp.getWriter().println("Counter = " + counter + "<BR>");
      try
      {
        Thread.currentThread().sleep((long) Math.random() * 1000);
        counter++;
      }
      catch (InterruptedException exc) { }
    }
    resp.getWriter().println("</BODY></HTML>");
  }
}

Naturally, the easiest approach is the most expensive. I would hate to dig into a project and see a servlet tagged by the SingleThreadModel interface unless the servlet was intended to be used in such a manner and the architecture supports this behavior. Use this method only after much consideration and try to avoid putting unnecessary constraints on your application.

Feeling thread-safe?

We now have an introduction to thread safety and the servlet container. We know a little about the servlet's lifecycle, how servlets and thread safety are related, as well as what our options are. Thread safety and multithreading are interesting topics and I encourage you to learn more about them.

The next time you experience inconsistent results and inaccurate data (especially results from references to objects) from your favorite servlet, start looking at your instance variables. Armed with this knowledge, you should be able to sniff out non-thread-safe code fairly quickly. Remember to look for variables that are both instance variables and used for referencing conversation-specific data. Go ahead, pull that thread.

Phillip Bridgham, M.S., is a technologist for Comtech Integrated Systems and a multitalented IT professional with more than 14 years of industry experience. He has worked in the e-commerce, industrial automation, business, research and development, financial, medical and embedded systems industries. Bridgham is a Sun Certified Web Component Developer and Sun Certified Java Programmer and is currently teaching Java courses at California State University, Sacramento, College of Continuing Education.

Learn more about this topic

This story, "Write thread-safe servlets" was originally published by JavaWorld.

Copyright © 2004 IDG Communications, Inc.

1 2 Page 2
Page 2 of 2