随机类线程安全吗?

时间:2011-04-28 13:47:32

标签: java multithreading random thread-safety

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

8 个答案:

答案 0 :(得分:62)

它是线程安全的,因为它在多个线程使用时仍然会生成随机数。

Sun / Oracle JVM实现使用synchronized和AtomicLong作为种子来提高跨线程的一致性。但它似乎并未在文档中的所有平台上得到保证。

我不会编写您的程序来要求这样的保证,特别是因为您无法确定将nextInt()调用的顺序。

答案 1 :(得分:23)

它是线程安全的,虽然并非总是如此。

有关详细信息,请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070

答案 2 :(得分:8)

根据文档,Math.random()保证多线程使用它是安全的。但是Random类没有。我会假设你必须自己同步。

答案 3 :(得分:7)

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

答案 4 :(得分:5)

如上所述,它是线程保存,但根据this article(链接死机)使用java.util.concurrent.ThreadLocalRandom可能是明智的。 ThreadLocalRandom也是Random的子类,因此它向后兼容。

  

该文章链接了不同Random的比较分析结果   课程:java.util.Randomjava.util.concurrent.ThreadLocalRandom   和java.lang.ThreadLocal<java.util.Random>。结果显示,   ThreadLocalRandom的使用效率最高,其次是   ThreadLocal和表现最差的随机本身。

答案 5 :(得分:4)

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

编辑:我刚刚注意到Sun的实现使用了AtomicLong,所以我猜这是线程安全的(Peter Lawrey也注意到了这一点)。

EDIT2 :OpenJDK也使用AtomicLong作为种子。正如其他人所说,虽然依靠这个仍然不好。

答案 6 :(得分: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());
    }
};

答案 7 :(得分:0)

没有为一个要在多个线程中使用的实例设置Random类。当然,如果你这样做,你可能会增加无法预测和接近随机数字的可能性。但由于它是一个伪随机生成器,我不明白为什么你需要共享一个实例。是否有更具体的要求?