Scala中的随机生成器是线程安全的吗

Is the random generator in Scala thread-safe

我有以下代码:

import scala.util.Random

val seq = Seq[Int](1, 2, 3)
val rand = new Random(123)
val gen = seq.par.map(_ => rand.nextInt(3))
println(gen.seq)

它打印出 Vector(2, 2, 2)
Scala 中的随机生成器似乎不是线程安全的?
是这样吗?如果是这样,除了为不同的线程使用不同的种子之外,我如何解决它。
此外,如果我在 Scala 中使用 Java 中的随机 class,它仍然是线程安全的吗?
相关问题


说明
par指的是scala.collection.parallel.immutable中的par。但我的电脑似乎不需要我这样做。它在我的电脑上运行。

是的。与 Java 中的相同。我们来看看next, which is the random generator behind nextInt:

的实现
protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
}

基本上我们根据seed计算下一个元素。如果 seed 已经更改,它将创建一个新的 nextseed,直到成功更新种子。因此它是线程安全的。

出于同样的原因,在您的场景中似乎并非如此。但是,如果我们 运行 相同而没有任何并行性,我们将得到相同的结果。

import scala.util.{Failure, Random, Success}

val seq = Seq[Int](1, 2, 3)
val rand = new Random(123)
val gen = seq.map(_ => rand.nextInt(3))
println(gen.seq)

结果为:

List(2, 2, 2)

代码 运行 在 Scastie。这是因为种子 123 的前三个“随机”数字是 2, 2, 2