Sei sulla pagina 1di 4

question:

When we implement singlethreadmodel it means that only one thread


can access the service method at a time.now my question is, why can't
we achieve the same thing by making the service() method
synchronized.
theory says that we shouldn't synchronize the service method.
But what will happen if we do so,except from the performance
problem?

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.

How do I ensure that my servlet is thread-safe?

The init() method is guaranteed to be called once per servlet instance,


when the servlet is loaded. You don't have to worry about thread safety
inside this method, since it is only called by a single thread, and the
web server will wait until that thread exits before sending any more
threads into your service() method.

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).

Under most circumstances, there is only one instance of your servlet,


no matter how many client requests are in process. That means that at
any given moment, there may be many threads running inside the
service() method of your solo instance, all sharing the same instance
data and potentially stepping on each other's toes. This means that
you should be careful to synchronize access to shared data (instance
variables) using the synchronized keyword.
(Note that the server will also allocate a new instance if you register
the servlet with a new name and, e.g., new init parameters.)

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.)

A simple solution to synchronizing is to always synchronize on the


servlet instance itself using synchronized (this) { ... }. However, this
can lead to performance bottlenecks; you're usually better off
synchronizing on the data objects themselves.

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.

See also What's a better approach for enabling thread-safe servlets


and JSPs? SingleThreadModel Interface or Synchronization?

To share data across successive or concurrent requests, you can use


either instance variables or class-static variables, or use Session
Tracking.

The destroy() method is not necessarily as clean as the init() method.


The server calls destroy either after all service calls have been
completed, or after a certain number of seconds have passed,
whichever comes first. This means that other threads might be running
service requests at the same time as your destroy() method is called!
So be sure to synchronize, and/or wait for the other requests to quit.
Sun's Servlet Tutorial has an example of how to do this with reference
counting.
destroy () can not throw an exception, so if something bad happens, call
log() with a helpful message (like the exception). See the closing a JDBC
connection example in Sun's Tutorial.

Potrebbero piacerti anche