Multithreading 在scala上生成线程本地对象

Multithreading 在scala上生成线程本地对象,multithreading,scala,singleton,Multithreading,Scala,Singleton,我正在用scala编写一个计算库。我将类似的功能归为原生scala单例对象,其中包含一系列过程和一些用于O(1)时态数据的静态分配内存 这种方法适合单线程使用。但同时从不同线程调用库函数可能会覆盖时态数据,并给调用者错误的答案 我可以通过将所有静态分配的内存移动到函数本地空间来复制这个库并编写线程安全版本。但我更喜欢通过定义线程局部变量来避免它 val tl = new ThreadLocal[String] tl.set("fish") tl.get // "fish" 在scala中可

我正在用scala编写一个计算库。我将类似的功能归为原生scala单例对象,其中包含一系列过程和一些用于O(1)时态数据的静态分配内存

这种方法适合单线程使用。但同时从不同线程调用库函数可能会覆盖时态数据,并给调用者错误的答案

我可以通过将所有静态分配的内存移动到函数本地空间来复制这个库并编写线程安全版本。但我更喜欢通过定义线程局部变量来避免它

val tl = new ThreadLocal[String]
tl.set("fish")
tl.get   // "fish"

在scala中可以吗?

只需使用Java的
Java.lang.ThreadLocal
类来存储变量

val tl = new ThreadLocal[String]
tl.set("fish")
tl.get   // "fish"

请注意,这样做会带来非零的性能损失(我记得,我手上大约有6纳秒)。如果您正在做一些非常轻量级的事情(例如增加索引),您可能会注意到速度上的差异。

自Java 8发布以来,有更多的声明性方式来初始化
ThreadLocal

Scala:

val local = ThreadLocal.withInitial[String](() => "init value");
ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init value");
val local = new ThreadLocal[String]{
  override def initialValue = "init value"
}
ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};
Java中的模拟:

val local = ThreadLocal.withInitial[String](() => "init value");
ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init value");
val local = new ThreadLocal[String]{
  override def initialValue = "init value"
}
ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};
Java中的模拟:

val local = ThreadLocal.withInitial[String](() => "init value");
ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init value");
val local = new ThreadLocal[String]{
  override def initialValue = "init value"
}
ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};
ThreadLocal=new ThreadLocal(){
@凌驾
受保护的字符串initialValue(){
返回“初始值”;
}
};
注意:
由于您传递的是
java.util.function.Supplier
lambda,当调用
ThreadLocal#get
时,该lambda只被评估一次,但之前没有评估过值。

还请注意,scala的
DynamicVariable
基本上是
InheritableThreadLocal
的包装器。不过,它没有为不可继承的线程局部变量提供任何选项。@Régis Jean Gilles可能与OP的问题没有严格的关系,但是:您提到的
InheritableThreadLocal
,由于池化,它似乎不能与
执行者
框架很好地结合。除了不推荐的
new Thread().start()
中保留的内容之外,是否还有此类变量的用例?
DynamicVariable
对于实现动态范围模式非常有用。通过示例查看我的其他答案:。但是,它决不能在多线程上下文中使用,因为在多线程上下文中它根本不起作用。