12

私はscalaで計算ライブラリを書いています。同様の機能を、一連のプロシージャとO(1)時間データ用に静的に割り当てられたメモリを含むネイティブのscalaシングルトンオブジェクトにグループ化します。

このアプローチは、シングルスレッドでの使用に適しています。ただし、異なるスレッドからライブラリ関数を同時に呼び出すと、一時データが上書きされ、呼び出し元に誤った応答が返される可能性があります。

このライブラリをコピーして、静的に割り当てられたすべてのメモリを関数のローカルスペース内に移動することで、スレッドセーフバージョンを作成できます。しかし、私はスレッドローカル変数を定義することによってそれを避けることを好みます。

Scalaでそれは可能ですか?

4

2 に答える 2

26

Javaのjava.lang.ThreadLocalクラスを使用して変数を格納するだけです。

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

これを行うと、ゼロ以外のパフォーマンスペナルティがあることに注意してください(私が覚えているように、私の手には最大6 ns)。非常に軽量な作業(インデックスのインクリメントなど)を行っている場合は、速度の違いに気付くかもしれません。

于 2013-01-05T20:25:30.230 に答える
10

Java 8のリリース以降、初期化するためのより宣言的な方法がありますThreadLocal

Scala:

val local = ThreadLocal.withInitial[String](() => "init value");

Javaのアナログ:

ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init value");

Java 8がリリースされるまでは、次のことを行う必要がありました。

Scala:

val local = new ThreadLocal[String]{
  override def initialValue = "init value"
}

Javaのアナログ:

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

注:java.util.function.Supplierが呼び出されたときに一度だけ評価されるラムダを渡しているThreadLocal#getが、値が以前に評価されていない ため、評価は遅延します。

于 2018-03-27T09:22:00.370 に答える