making thread-local objects on scala
Solution 1
Just use Java's java.lang.ThreadLocal
class to store the variables.
val tl = new ThreadLocal[String]
tl.set("fish")
tl.get // "fish"
Be aware that there is a nonzero performance penalty for doing this (~6 ns in my hands, as I recall). If you're doing really lightweight stuff (e.g. incrementing an index), you might notice the difference in speed.
Solution 2
Since Java 8 release, there is more declarative way to initialize ThreadLocal
:
Scala:
val local = ThreadLocal.withInitial[String](() => "init value");
Analogue in Java:
ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init value");
Until Java 8 release you had to do the following:
Scala:
val local = new ThreadLocal[String]{
override def initialValue = "init value"
}
Analogue in Java:
ThreadLocal<String> local = new ThreadLocal<String>(){
@Override
protected String initialValue() {
return "init value";
}
};
Note:
Evaluation is lazy since you are passing java.util.function.Supplier
lambda that is evaluated only once when ThreadLocal#get
is called but value was not previously evaluated.
ayvango
Updated on June 03, 2022Comments
-
ayvango almost 2 years
I'm writing a computational library in scala. Similar functionality I group into native scala singleton objects containing bunch of procedures and some statically allocated memory for O(1) temporal data.
This approach is suited for a single-thread use. But calling library functions from different threads simultaneously may overwrite temporal data and give incorrect answers to callers.
I may just copy this library and write thread-safe version by moving all statically allocated memory inside functions local space. But I prefer to avoid it by defining thread-local variables.
Is it possible in scala?
-
Régis Jean-Gilles over 11 yearsAlso note that there is scala's
DynamicVariable
which is basically a wrapper aroundInheritableThreadLocal
. It does not provide any option for non-inheritable thread locals though. -
idonnie over 11 years@ Régis Jean-Gilles Maybe it's not related strictly to OP's question, but: you mentioned
InheritableThreadLocal
, seems it does not combines well withExecutors
framework because of pooling. Is there a use case for such variables, besides stuff that is keeped in deprecatednew Thread().start()
? -
Régis Jean-Gilles over 11 years
DynamicVariable
is useful for implementing the dynamic scope pattern. See my other answer by example: stackoverflow.com/a/13252952/1632462. However it must never be used in a multi-threaded context, where it just won't work.