Alan.Bateman at oracle.com
Sun Dec 9 20:12:58 UTC 2018
On 09/12/2018 15:49, Brian Goetz wrote:
> Right now, we’ve got ThreadLocal. It is usually used as an approximation for what we really wan but we don’t have. TL is what we’ve got, so we use it for a lot of things. Ron and Alan spent some time categorizing the various use cases, and we looked at them and asked which of them are good uses and which are abuses, and for those that are abuses, what a better mechanism might be. I’ll defer to Ron and Alan to provide a more complete list, but I’ll sketch out some canonical examples from each category (probably forgetting one):
Your list is a good summary. The forgotten one is "task local",
essentially just extending the task with fields. That one is bit
limited, at least for library code where there won't be knowledge about
the task that is running it.
> - Proxy for processor-local
> - Contention-avoidance schemes
This one is somewhat specialized and too early to say if it make sense
to expose as an API or not. For now, it's the "processorid" branch in
the loom repo where there is an Unsafe method to get the processor id.
Rickard has done good work on an intrinsic so it compiles to the fastest
instruction for the processor (linux-x64 only for now). There isn't a
ProcessorLocal<T> or anything else making use of it at this time as
there is a lot more investigation and experimentation needed. We're
hoping Doug will find time to see if j.u.c. could use it, maybe
Striped64. I assume TLR won't use it and will need to continue to make
use of TLR fields on the (carrier) Thread.
> - Proxy for frame-local
> - Transaction IDs, caller context, etc (EE uses this ubiquitously)
> - Other framework-specific implicit arguments or context
This is the focus of the discussion in this thread. It's not hard to
find examples where a framework or library sets a TL with some context
that is accessed by some callee that is many stack frames from where the
local was set. A common pattern is set a TL with some context object,
perform some action that may need the context, and restore/remove the
local in a finally block. We found several places where there is nesting
so the setup involves saving the old context before "pushing" the new
context. The finally block just restores the previous context. There are
several examples in Jetty and Jersey that do exactly this.
> - Caches
> - Objects that are expensive to create, such as SimpleDateFormat
The common pattern seems to be objects that are not thread safe and are
expensive to create. We've seen many cases where SimpleDateFormat
objects are cached in a TL. In the JDK, CharsetEncoder/CharsetDecoder
objects are examples that they cached in several TLs.
> (Stepping back further, the bigger goal here is that, if we have the right mechanisms, we don’t have to make such heroic efforts to make fibers support thread locals, meaning that we will get to the fiber mechanism we really want, rather than the one tied to the legacy of what we have.)
I'm sure there will be demands for fiber locals but we'd like push back
for as long as possible to give time to explore and try out and
hopefully prove better alternatives.
More information about the loom-dev