随机类线程安全吗?


110

Random在多个线程之间共享该类的一个实例是否有效?并nextInt(int)特别从多个线程调用?


@Bala R,不,我们不是在谈论C#的Random对象,而是Java。
Buhake Sindi

哎呀 抱歉错过了那部分。
Bala R

小心在多线程环境中使用Random获取数字可能会给您带来不好的结果。
Maxence SCHMITT

14
对于更多读者:有一个名为1.7的新类java.util.concurrent.ThreadLocalRandom
Jin Kwon

Answers:


66

从某种意义上讲,它是线程安全的,当被多个线程使用时,它仍然会生成随机数。

Sun / Oracle JVM实现使用同步和AtomicLong作为种子来提高线程之间的一致性。但是,文档中似乎并没有在所有平台上对此进行担保。

我不会编写要求这种保证的程序,尤其是在您无法确定nextInt()调用顺序时。


69
Java 7文档中已添加保证:“ java.util.Random的实例是线程安全的。” docs.oracle.com/javase/7/docs/api/java/util/Random.html
Matt R



7

是的,Random是线程安全的。该nextInt()方法调用受保护的next(int)方法,该方法使用AtomicLong seed, nextseed(原子长)来生成下一个种子。AtomicLong用于种子生成时的线程安全。


6

如前所述,这是节省线程的,但是java.util.concurrent.ThreadLocalRandom根据本文的用法(链接失效)可能是明智的。ThreadLocalRandom还是Random的子类,因此它向后兼容。

该文章链接了不同Random类的比较分析结果java.util.Randomjava.util.concurrent.ThreadLocalRandomjava.lang.ThreadLocal<java.util.Random>。结果表明,使用ThreadLocalRandom的性能最高,其次是ThreadLocal,而性能最差的Random本身。


4

没有理由多个线程不能全部使用同一个随机变量。但是,由于该类不是显式线程安全的,而是通过种子维护了一系列伪随机数。多个线程可能最终具有相同的随机数。最好为每个线程创建多个“随机数”并以不同的种子进行播种。

编辑:我刚刚注意到Sun的实现使用AtomicLong,所以我想这是线程安全的(也由Peter Lawrey(+1)指出)。

EDIT2:OpenJDK还使用AtomicLong作为种子。正如其他人所说,依靠它仍然不是很好。


3

在不假设Random使用原子变量的情况下,这是我处理问题的方式。如果currentTime * thread id将来某个时间相等,它仍然可以随机碰撞,但这对于我的需求来说已经足够了。为了真正避免冲突的可能性,您可以让每个请求都等待唯一的时钟时间戳。

/**
 * Thread-specific random number generators. Each is seeded with the thread
 * ID, so the sequence of pseudo-random numbers are unique between threads.
 */
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
    @Override
    protected Random initialValue() {
        return new Random(
            System.currentTimeMillis() *
            Thread.currentThread().getId());
    }
};

向上!问:(24*60*60*1000)重要吗?
Jin Kwon

1
是的,那是一个肮脏的解决方法。该(24*60*60*1000)是如此,与ID的线程12xxxxxxxxxx045米利斯没有获得种子一样线程22xxxxxxxxxx035米利斯。但是,我没有充分的理由认为线程ID是增量的,也没有充分的理由认为我明天将在比今天更多的随机时间创建线程。我现在简化了算法,并更新了说明以找出缺点。
瑞安

0

Random类没有设立一个实例在多个线程中使用。当然,如果您这样做,可能会增加获得不可预测的且接近随机数的可能性。但是由于它是一个伪随机数生成器,所以我看不到为什么需要共享一个实例。还有更具体的要求吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.