Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Assume that you write a servlet and synchronize the service (...) (or any of the
doXXX(...) methods or any method you call from any of these methods). Once you
deploy the servlet, the servlet container receives ten "near-simultaneous" requests for
the servlet. Upon receipt of the first request, the servlet container kicks off a thread
and sends it on its way (i.e. starts it executing the service(...) method).
Unbeknownst to the servlet container, the thread executing in the
service(...) method "locks the door" behind it (holds the lock for the
servlet object). Not knowing any better, the servlet container starts the
other nine threads and assumes they are happily executing the
service(...) method. In reality, each of the nine other threads finds the
object (the servlet instance) locked, so they go into a "wait" state.
Meanwhile, the first thread finishes executing the service(...) method,
so it releases the lock on the servlet instance. One of the other
threads--not necessarily the second thread, so we'll say the eighth
thread--awakens to find the servlet's lock available, so it requests the
lock and starts processing the service(...) method. Meanwhile, the
servlet container may be receiving other requests. It's possible that
when the eighth thread (which was the second to execute the
service(...) method) finishes, the thirty-fifth thread grabs the lock.
With this approach each thread has an "equal" probability of being the
next allowed to execute the service(...) method. It's complete anarchy--
every thread for itself. About this time, the person who sent the second
request is calling you to say that your application is down. :) And, if you
really want things to get complex, try synchronizing the service (...)
method and the doXXX(...) methods...
So what does the servlet container do? It provides queuing and
prioritization (generally first-in-first-out) of requests.
Some servlet containers instantiate multiple servlet objects (and
maintain a servlet pool--remember that synchronizing a method locks
the object (or instance), not the method, so multiple threads can
execute the same method in different instances) to handle multiple
simultaneous requests. (Note that this means that you may need to
synchronize access of static members.)
Others (like Tomcat, IIRC) provide as little support for
SingleThreadModel servlets as is required by the servlet specification
(they don't waste time creating object pools) since using
SingleThreadModel is a "cop out." Keep reading, I'll explain why... :)
Implementing the interface often gives developers a false sense of
security when it comes to multi-threaded programming. For example,
regardless of whether your servlet implements SingleThreadModel or
not, you still need to consider synchronization problems with static
members, HttpSession attributes, ServletContext attributes, and any
other classes outside the scope of the servlet (i.e. JavaBeans, support
classes, etc.).
So, what do you do if you're not sure whether your servlet is thread-
safe? Your best bet is to talk with other developers who have more
experience in multi-threaded programming (some
one who's been doing it for 30 years is a good beginner ;). Also, do all
you can to learn about the topic. IBM's DeveloperWorks website has a
lot of articles on multi-threaded programming, including Understand
that for instance methods, synchronized locks obj..., Threading lightly,
Part 1: Synchronization is not the enemy (and parts 2 and 3), and
many, many more. Also, check out some of their tutorials, like
Introduction to Java threads.
Every new client request generates (or allocates) a new thread; that
thread calls the service () method of your servlet (which may in turn
call doPost (), doGet () and so forth).
Note that you need not (and should not) synchronize on local data or
parameters. And especially you shouldn't synchronize the service ()
method! (Or doPost (), doGet() et al.)
If you absolutely can't deal with synchronizing, you can declare that
your servlet implements SingleThreadModel. This empty interface tells
the web server to only send one client request at a time into your
servlet. From the JavaDoc: If the target servlet is flagged with this
interface, the servlet programmer is guaranteed that no two threads
will execute concurrently the service method of that servlet. This
guarantee is ensured by maintaining a pool of servlet instances for
each such servlet, and dispatching each service call to a free servlet. In
essence, if the servlet implements this interface, the servlet will be
thread safe Note that this is not an ideal solution, since performance
may suffer (depending on the size of the instance pool), plus it's more
difficult to share data across instances than within a single instance.