Math.random()究竟何时播种?

时间:2012-03-14 09:05:34

标签: java random thread-safety

根据文件:

  

首次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式

一样
new java.util.Random
     

此新的伪随机数生成器此后用于对此方法的所有调用,并且在其他任何地方都不使用。

我对“首次调用此方法时”的范围感到困惑 - 当我的应用程序首次调用它时它是不是?无论我的应用程序做什么,它是否只播种过一次?

2 个答案:

答案 0 :(得分:2)

首次调用方法Math.random()时初始化它。

有趣的是,在Java 5和6中,代码使用broken double-checked-locking pattern,因此它的不是线程安全,即使它看起来像是。

[编辑] 正确的代码如下所示:

private static volatile Random randomNumberGenerator; // broken without volatile

或者更昂贵:

public static synchronized double random() {
    ...
}

[EDIT2] 官方错误:Math.random() / Math.initRNG() uses "double checked locking"

答案 1 :(得分:0)

查看源代码,Math.random()的相关代码定义为:

private static Random randomNumberGenerator;

private static synchronized void initRNG() {
    if (randomNumberGenerator == null) 
        randomNumberGenerator = new Random();
}

public static double random() {
    if (randomNumberGenerator == null) initRNG();
    return randomNumberGenerator.nextDouble();
}

因此,randomNumberGeneratorstatic变量,一旦通过JVM中的任何类调用它来初始化(第一次调用Math.random()),它就会停留在那里(除非不再需要和卸载课程。