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