DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=3884>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=3884

SingleThreadModel servlets not pooled results in low performance





------- Additional Comments From [EMAIL PROTECTED]  2001-10-02 08:50 -------
NOTE:  Tomcat 4 *does* obey the spec requirements related to SingleThreadModel
(only one request at a time per instance).  It just does not pool them.
==============================================================================

The "promise" of SingleThreadModel, especially if you are a new developer that
is unfamiliar with multithread environments, is that you don't have to worry
about threads at all.  But this is completely untrue if your application uses
sessions - it is still very easy to have multiple threads talking to the same
session at the same time.  Consider some of the ways that this can happen:

* UI with multiple frames (the browser will make simultaneous requests).

* UI with dynamically created images (simultaneous requests for the same
  reason that frames cause them).

* User starts a long transaction, presses STOP, then goes somewhere else.

In each case, the expectation that the developer doesn't have to worry about
threads is not met.  If they don't synchronize use of their session attribute
variables appropriately, they are still going to have problems.

Ironically, pooling of SingleThreadModel instances (if it were implemented) also
violates another expectation that developers are used to in non-STM servlets -
that there is only one instance of a particular servlet per <servlet>
definition.  In web apps, it is common to use instance variables to share
application-wide things (like connection pools and hit counters) across all
users of that servlet.  But this doesn't work in an STM servlet that really is
pooled.

Further, good multithreading design patterns encourage you to minimize the need
for locking (typically implemented with synchronization in Java) - and, when you
do lock, you should lock on the smallest unit that is possible.  Locking the
entire service() method, which is what STM does, is far too heavyweight.  An
example of this comes from the implementation (inside Tomcat) of the HttpSession
interface, where you have methods like getAttribute() and setAttribute() that
need to lock the internal HashMap containing those attributes.  However, instead
of synchronizing on the entire session object (which is similar to what STM does
on the entire servlet), the internal code locks *only* on the attributes
collection:

  public void setAttribute(String name, Object value) {
    ...
    synchronized (attributes) {
      ...
      attributes.put(name, value);
      ...
    }
    ...
  }

so that no other calls to the session that are happening at the same time from
other threads (like getId() or setMaxInactiveInterval()) are affected by these
locks.  This approach maximizes the concurrency - and applications should use
similar design patterns for similar reasons.  Otherwise, you are needlessly
slowing down your application even if pools of STM servlets are available.

Finally, there don't seem to be any compelling use cases for SingleThreadModel
that cannot be solved using multithread design techniques -- usually, the only
thing you need to do is utilize local variables instead of instance variables
for per-request state information.  So why go to the effort of teaching people
two design patterns instead of one?  

I've followed mailing lists like TOMCAT-USER and SERVLET-INTEREST for several
years, and I have seen far too many developers code themselves into corners
based on mistaken assumptions about how SingleThreadModel works.  I'd rather not
encourage it - but if someone wants to propose a patch to enable this, that's OK
too (as long as it complies with the spec requirements).

Reply via email to