[concurrency-interest] Soliciting input about removeAllThreadLocals

Joshua Bloch joshua.bloch@sun.com
Mon, 09 Dec 2002 09:54:12 -0800


Miles,

   Thanks for digging this up.  It dates from '97(!)  Let's go down the 
list :

>    1) Associating "genuine thread context" with a thread - The context
>       is typically temporary  (e.g., the user or transaction on whose
>       behalf a thread is currently executing, the prevailing rounding
>       mode or precision for some class of numerical computation, the
>       operative permissions).
>
    In order to use these properly, you *must* use them with try-finally 
blocks, e.g.:

    beginTransaction();
    try {
        ... // do the work
    } finally {
        endTransaction();
    }

If you don't do this, you'll get hurt, whether or not you use thread 
pools.  If you use the API correctly, removeAllThreadLocals would be a 
no-op, or perhaps a minor performance loss.  If you use the API 
incorrectly, removeAllThreadLocals would sweep the problem under the 
rug, but I don't see this as a major win, or even a good idea.

>  Less frequently, there may be used for permanent thread context.
>
The "unique name for the purposes of logging" example reflects this 
usage.  removeAllThreadLocals would be actively harmful.

>    2) Performance - Some objects are, by their nature "thread singleton
>       objects": while they do not represent true thread context, a
>       given thread will never use more than one of them.  If they are
>       expensive to construct, it makes sense to permanently associate
>       one with
>       a thread the first time the thread needs such an object.  This
>       differs from case 1 in that the object doesn't maintain any
>       interesting state between uses.  An example might be an open
>       connection to a database.
>
The example I chose was somewhat unfortunate.  I don't think it's worth 
jamming such an expensive resource onto a thread.  But, for example, 
StringBuffer now (as of 1.4.2) associates a scratch buffer with each 
thread (based on extensive measurements).  The removeAllThreadLocals 
call would negate some of the performance benefit from this usage, but 
wouldn't cause serious problems.

>
>    3) Sleazery - Thread-local variables can be used to effectively
>       add extra parameters (in or out) to a method without changing
>       its signature.  This is not terribly good practice, and should
>       rarely, if ever, be necessary.
>
But it is.  Unfortunately, you end up operating in worlds where you call 
a which calls b which calls c, which is back in your class, and you 
really need to get some information to c.  This situation is very rare, 
but when it happens ThreadLocal can be a lifesave.  It hasn't happened 
to me in the past five years, but it has happened to other people I 
know.  It tends to happen in the context of overly rigid frameworks. 
 This is a short-term use of ThreadLocal, and removeAllThreadLocals() 
neither helps nor hurts

>    4) Making legacy APIs thread-safe - Back in the bad old days,
>       statics were used to hold state from  call-to-call (e.g.,
>       strtok()) or to return supplemental information (e.g., errno). 
>       Such APIs can be made thread-safe by replacing statics with
>       thread-locals. Hopefully we have no such legacy APIs in the Java
>       world.
>
I think I was correct when I said that this was irrelevant to the Java 
platform, but the same conculsion as for 3 applies:  This is a 
short-term use of ThreadLocal, and removeAllThreadLocals() neither helps 
nor hurts

  I think it's fair to say that in the context of this taxonomy, the 
removeAllThreadLocals call does more harm than good.

                Regards,

                Josh