在scala上创建线程局部对象

ayv*_*ngo 11 singleton multithreading scala

我正在用scala编写一个计算库.类似的功能我组成本机scala单例对象,包含一堆过程和一些静态分配的内存,用于O(1)时间数据.

此方法适用于单线程使用.但是同时从不同的线程调用库函数可能会覆盖时态数据并给调用者提供错误的答案.

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

scala中有可能吗?

Rex*_*err 25

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

val tl = new ThreadLocal[String]
tl.set("fish")
tl.get   // "fish"
Run Code Online (Sandbox Code Playgroud)

请注意,执行此操作会产生非零性能损失(我记得在我手中约为6 ns).如果你正在做很轻量级的东西(例如递增索引),你可能会注意到速度的差异.

  • 另请注意,scala的`DynamicVariable`基本上是`InheritableThreadLocal`的包装器.但它不为不可继承的线程本地提供任何选项. (4认同)

And*_*mov 5

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

斯卡拉:

val local = ThreadLocal.withInitial[String](() => "init value");
Run Code Online (Sandbox Code Playgroud)

Java中的模拟:

ThreadLocal<Cipher> local = ThreadLocal.withInitial(() -> "init value");
Run Code Online (Sandbox Code Playgroud)

在Java 8发布之前,您必须执行以下操作:

斯卡拉:

val local = new ThreadLocal[String]{
  override def initialValue = "init value"
}
Run Code Online (Sandbox Code Playgroud)

Java中的模拟:

ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};
Run Code Online (Sandbox Code Playgroud)

注意: 评估是惰性的,因为您传递的java.util.function.Supplierlambda仅在ThreadLocal#get被调用时进行评估,但之前未评估过值.