[concurrency-interest] Soliciting input about removeAllThreadLocals

Joshua Bloch joshua.bloch@sun.com
Sun, 08 Dec 2002 10:30:35 -0800



>  Many years ago, when I was a young programmer, an older and wiser man 
> explained one of the most important precepts of good programming to me 
> thus:  Global Variables Are Bad.
>  Like all such rules, this one has exceptions.  But with this precept 
> in my mind, I generally ask myself some tough questions when tempted 
> to create a static variable.  In particular: "What is it about this 
> variable that is aligned with every process that might run this code? 
> Are you absolutely sure you will never want two different values for 
> this variable within the same process?"
>  The usual reason for creating a global variable is laziness.  The 
> second most usual reason is unjustified optimization. 

   All this is true.

> All of this is by way of explaining why I avoid ThreadLocal like the 
> plague.    Thread-local variables are just global variables in disguise.

   This is utter nonsense.  Jim Waldo believes (or perhaps believed) it 
with all his heart and soul, but it's still utter nonsense.  ThreadLocal 
variables are among the least "gloabal-like" of all variables. 
 Thread-locality is orthongonal to other aspects of visibility: you can 
have a ThreadLocal local variable, a ThreadLocal class variable, a 
ThreadLocal instance variable, and so forth.  In *every* case, the 
ThreadLocal version is more "local" (i.e., provides less information 
sharing) than the "normal" version.

>  The same tough questions apply to them, substituting "thread" for 
> "process".  And the same main reason for using them -- laziness -- 
> also applies.
>  In fact, thread-local variables are worse than global variables in at 
> least one respect, for exactly the issue you raise here: the same 
> thread might well be used for more than one purpose. 

   This is a blame-the-victim mentality.  Blindly reusing a Thread for 
more than one purpose (e.g., through thread pooling) is dangerous.  It's 
generally done for the purpose optimization.

>  The thing is, this is not a new issue.  People have been using thread 
> pools in Java forever.  And have been battling the problems you 
> discuss just as long. 

   Yep.  Thread pools are dangerous.  ThreadLocals, on the other hand, 
are not.

>  I have encountered those subtle bugs you describe that arise from the 
> same thread being reused but its thread-local variables not being 
> reinitialized.  They definitely happen.  The case I have in mind was a 
> servlet-based web application.  We stored database connections in 
> thread-local variables.  Problems arose when some threads needed to 
> set different parameters for these connections from others, or needed 
> to talk to a different database.  But the solution was not to 
> reinitialize everything each time.  The solution was to recognize that 
> there was nothing about a database connection that was inherently 
> unique to a thread.  As soon as we separated database connections from 
> threads, we found that many of the complicated workarounds we had 
> written were suddenly superfluous.  For example, establishing two 
> database connections had formerly required a second thread; now we 
> simply went to our cache a second time within the same thread, an 
> enormous simplification.
>  So, I'm equanimous on the subject of whether ThreadLocals should be 
> cleared on each use of a thread.  I won't use them regardless.

  Too bad.  They're a useful tool  You can use them to keep track of 
thread scopes.  You can use them to safe, fast lazy initialization of 
per-instance state.  You can use them to assign unique IDs to threads. 
 And yes, you can also use them to hold "thread singleton objects." 
 This technique is often preferable to an instance pool (e.g. a 
connection pool), as the pool can become an unnecessary concurrency 



P.S.  I added ThreadLocal to the libraries, and I had to fight hard to 
get them in.  I have no doubt that I did the right thing when I added 
them.  Yes, they're open to abuse, but so is everything else.