-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

David,

On 3/10/15 8:15 PM, David Bullock wrote:
> On 11 March 2015 at 04:43, Christopher Schultz
> <ch...@christopherschultz.net
>> wrote:
> 
> Basically, making a
>> servlet threadsafe only requires you to avoid any non-threadsafe
>> class members in the servlet itself...
> 
> Since we're tossing pennies, I've often wondered how the
> app-server achieves the effect that any instance-level fields set
> during an overridden setInitialContext(ServletContext) are
> guaranteed to 'happens-before' subsequent reads from overridden
> service(...) methods.

Do you mean init(ServletConfig) and other, similar things (like
ServletContextListeners, ServletContainerInitializers, Filters,
annotations, etc.)?

> I can only guess that the thread which invokes setInitialContext
> is the very same thread which *later *invokes aThread.start() on
> the worker threads

No, it's not necessarily that thread. Also, remember that the servlet
context (aka web app) can be un-deployed and re-deployed while the
server continues to run and serve requests.

So it's not that the threads aren't (yet) serving requests, it's that
the container knows that servlets must be initialized before they can
be used.

Conceptually, you can think of the container doing something like this:

1. Map the incoming request to a web application
2. If the web application is (re)loading, stall the request
   Resume the request once the application is running again
3. Process the request by sending it through the filter chain
4. Process the request by sending it to the servlet

During (re)loading, the container marks the web application is
(re)loading, then initializes everything, then marks it as available.
These two processes (reloading and dispatching) can happen at any time
with respect to each other, so it's not a trick of nicely-timed threads.

Remember that threads just execute code; they won't have minds of
their own. The code they execute maintains coordination between the
different parts of the system. So, it's the request processing thread
itself that stalls while the web application is re-loading (in another
thread). The container is managing both of those processes because the
container's code is being executed by both threads, and can therefore
synchronize on appropriate objects, etc.

> ... there is a 'happens-before' relationship there, and since
> there is no volatile, final or synchronization involved, that's
> probably the one ... is it?

Remember that there is more code running than just what's in the
servlet. There is plenty of synchronization (though one technique or
another, not necessary using the "synchronized" keyword directly)
within the container itself within the container.

> That would kind of mean that when reloading a webapp, one would
> have to restart all the worker threads, right? Any comments?

No, they can keep going.

Tomcat actually does re-new request processing threads in the event
that a web application has left a ThreadLocal object whose Class was
loaded by the web applications' ClassLoader. If Tomcat didn't do that,
web applications could leave a huge footprint in the heap even after
they had been un-deployed.

> (I ask these only from curiosity).
> 
> I stumbled across this in my IDE when I used an @ThreadSafe
> annotation on my servlet, but could put no @GuardedBy annotations
> on any of the instance fields, because I'm *not* actually using a
> lock or a synchronized block. (Thus my IDE whinged at me, and I
> retracted the @ThreadSafe from the Sevlet).

I can't comment on the use of annotations, since I am largely ignorant
of their use and implications (because I'm a hater), but that's the
IDE imposing that limit on you, not the compiler or the runtime.

I've found that it's rarely necessary to have instance fields in a
Servlet except for things that are really globally-accessible (to the
servlet, of course... anything truly global should be in a
ServletContext attribute). Anything that is an instance field must
either be threadsafe itself (e.g. java.util.Hashtable,
java.util.concurrent.ConcurrentHashMap, or a collection wrapped in
java.util.Collections.synchronized(Collection|List|Map)), or used in a
way that makes it thread-safe (e.g. wrap a synchronized{} block around
the usage, or restrict usage to a synchronized method -- which has the
same effect.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: GPGTools - http://gpgtools.org

iQIcBAEBCAAGBQJVAD44AAoJEBzwKT+lPKRYfTIQAI+SmQ0RApZwrFRp9rnx786J
mjLnckm33vhUf+btgT5733OUQF2a+Jmj76SuESuyI7JA3ozPlj5UX0Mr+1TJPrK8
NYzBTSDeFJoM1pojR73PMWUaurEzFG6c517VYKrNEhrKNBdwYB3Tha3mW6uobn/R
v/0HBhC/hROjFtAdD6kymtBCO6ToH+3F5NuaizzF44cMy1IrxcYWhe5a4Xf69mVR
4P4rfXtztGULG+BUK2aTdwMYU0QLqae8MGDwYIhuJ2H1ExuF6mhWtH20+U8ZbTSI
NckLWsMTyNOcVS86W++Ceoq2/qmP79thqN8tPy5Z7vL/+qZ8JeKlKPKPaUPpFHY6
lsKMZ0SFCefHPKbVVD/5sH77G7YptZn92asgpZMVh4dGIBsSTangveSnjMqSO4G5
F9U07oU2QemGQ4dK15KpNqis4aFQKCX9EiKwRSFlBe/bVFc64YfSCUlitiuU1wiR
w29L+Rc04cZ0ImbLTsTunFK0SSKlUGxI5UwZ3dPadrl/TyV6oKTqjFCVYc1a0ZtV
WR3PJTFsfWs0zXtTFDZqtWVSNatjDXnRsGIxksPFTceZ0oU8r94PQux13yNAz56N
nr4iSEnrBg7IOPBFt2UZvPwWDGohTYwncLJF7fsOnjr4NWrBRIts3eZCnw9hPVcC
0CtHKu08oCm7ra92H//D
=CicN
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to