making thread-local objects on scala

10,696

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.

Share:
10,696
ayvango
Author by

ayvango

Updated on June 03, 2022

Comments

  • ayvango
    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
    Régis Jean-Gilles over 11 years
    Also note that there is scala's DynamicVariable which is basically a wrapper around InheritableThreadLocal. It does not provide any option for non-inheritable thread locals though.
  • idonnie
    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 with Executors framework because of pooling. Is there a use case for such variables, besides stuff that is keeped in deprecated new Thread().start() ?
  • Régis Jean-Gilles
    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.