You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Nick Williams <ni...@nicholaswilliams.net> on 2013/03/15 21:53:38 UTC

ThreadLocal variables and BIO/NIO/APR

I know, I know. "Don't use ThreadLocals." I've seen it on this list at least 100 times. But avoiding ThreadLocal variables can be hard:

1) Spring Framework uses ThreadLocals for things like the RequestContext. You can't just turn that off.
2) Spring Security uses ThreadLocals for things like the security context. Can't turn that off, either.
3) Using ServletRequest#setAttribute()/getAttribute() or HttpSessions aren't always useable replacements for ThreadLocal variables. Doing this couples all aspects of your application to ServletRequests and/or HttpSessions. For example, in a multi-tenant environment, you need to establish some context that identifies which persistence location to use for obtaining and persisting data. Having to pass a request or session from servlet to service to repository is not ideal. Neither, for that matter, is having to have a "tenant" parameter (or any other type of identifying parameter) added to every single method in the entire application. And, when you're dealing with existing interfaces (Spring, Hibernate) that you have to implement, this isn't even an option sometimes.

So, with that in mind, the logical question is, how does one use ThreadLocals safely and reliably? The obvious first step is, "don't let them leak." That's easily solved. We have a filter that performs the setting of all of our ThreadLocals on the way in, and it also clears them on the way back out.  The ThreadLocalLeakPreventionListener helped us identify 1 or 2 situations where they were still leaking, and we fixed those, too. But, reading about the differences between BIO/NIO/APR, I'm concerned that may not be enough.

If I understand this correctly (which I may not), BIO dedicates a thread to a request from beginning to end and then recycles that thread only when the request has completed (which is perfect), but NIO and APR do not do that. More than one request may use a given thread at (kind of) the same time. So my concern is that ThreadLocals from one request could pollute ThreadLocals in another request. Is this a concern, or are there reasons that won't happen?

I don't really understand how any of this works, so some advice is greatly appreciated.
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: ThreadLocal variables and BIO/NIO/APR

Posted by Konstantin Kolinko <kn...@gmail.com>.
2013/3/16 Nick Williams <ni...@nicholaswilliams.net>:
> I know, I know. "Don't use ThreadLocals." I've seen it on this list at least 100 times. But avoiding ThreadLocal variables can be hard:
>
> 1) Spring Framework uses ThreadLocals for things like the RequestContext. You can't just turn that off.
> 2) Spring Security uses ThreadLocals for things like the security context. Can't turn that off, either.
> 3) Using ServletRequest#setAttribute()/getAttribute() or HttpSessions aren't always useable replacements for ThreadLocal variables. Doing this couples all aspects of your application to ServletRequests and/or HttpSessions. For example, in a multi-tenant environment, you need to establish some context that identifies which persistence location to use for obtaining and persisting data. Having to pass a request or session from servlet to service to repository is not ideal. Neither, for that matter, is having to have a "tenant" parameter (or any other type of identifying parameter) added to every single method in the entire application. And, when you're dealing with existing interfaces (Spring, Hibernate) that you have to implement, this isn't even an option sometimes.
>
> So, with that in mind, the logical question is, how does one use ThreadLocals safely and reliably? The obvious first step is, "don't let them leak." That's easily solved. We have a filter that performs the setting of all of our ThreadLocals on the way in, and it also clears them on the way back out.  The ThreadLocalLeakPreventionListener helped us identify 1 or 2 situations where they were still leaking, and we fixed those, too. But, reading about the differences between BIO/NIO/APR, I'm concerned that may not be enough.
>
> If I understand this correctly (which I may not), BIO dedicates a thread to a request from beginning to end and then recycles that thread only when the request has completed (which is perfect), but NIO and APR do not do that. More than one request may use a given thread at (kind of) the same time. So my concern is that ThreadLocals from one request could pollute ThreadLocals in another request. Is this a concern, or are there reasons that won't happen?
>
> I don't really understand how any of this works, so some advice is greatly appreciated.


Java call chain belongs to a single thread. That is how the language
works, regardless of connectors. As long as you clear it in the same
place where you set it (a-la try/finally)  you should not worry.

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


Re: ThreadLocal variables and BIO/NIO/APR

Posted by Nick Williams <ni...@nicholaswilliams.net>.
On Mar 15, 2013, at 4:05 PM, Mark Thomas wrote:

> On 15/03/2013 20:53, Nick Williams wrote:
>> If I understand this correctly (which I may not), BIO dedicates a
>> thread to a request from beginning to end and then recycles that
>> thread only when the request has completed (which is perfect), but
>> NIO and APR do not do that. More than one request may use a given
>> thread at (kind of) the same time. So my concern is that ThreadLocals
>> from one request could pollute ThreadLocals in another request. Is
>> this a concern, or are there reasons that won't happen?
> 
> Normally, all three connectors dedicate a thread to the processing of a
> request from beginning to end. You can safely use ThreadLocals in the
> manner you describe with any connector.
> 
> However, if you start to use Servlet 3.0 Async then you need to be a
> little more careful. Once you enter async mode ThreadLocals are almost
> certainly going to start causing problems. The same goes for Servlet 3.1
> non-blocking IO.
> 

Ahh. That makes sense. We are not currently using Async or non-blocking IO. We may at some point in the future. We will be sure to be careful with how we handle ThreadLocals at that point. Thanks!
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: ThreadLocal variables and BIO/NIO/APR

Posted by Mark Thomas <ma...@apache.org>.
On 15/03/2013 20:53, Nick Williams wrote:
> If I understand this correctly (which I may not), BIO dedicates a
> thread to a request from beginning to end and then recycles that
> thread only when the request has completed (which is perfect), but
> NIO and APR do not do that. More than one request may use a given
> thread at (kind of) the same time. So my concern is that ThreadLocals
> from one request could pollute ThreadLocals in another request. Is
> this a concern, or are there reasons that won't happen?

Normally, all three connectors dedicate a thread to the processing of a
request from beginning to end. You can safely use ThreadLocals in the
manner you describe with any connector.

However, if you start to use Servlet 3.0 Async then you need to be a
little more careful. Once you enter async mode ThreadLocals are almost
certainly going to start causing problems. The same goes for Servlet 3.1
non-blocking IO.

Mark

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