Random 类线程安全吗?

发布于 2024-11-04 08:17:52 字数 73 浏览 0 评论 0 原文

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

Is it valid to share one instance of the Random class between multiple threads? And to call nextInt(int) from multiple threads in particular?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

玩套路吗 2024-11-11 08:17:53

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

Sun/Oracle JVM 实现使用synchronized 和AtomicLong 作为种子来提高线程间的一致性。但文档中似乎并不能保证它适用于所有平台。

我不会编写需要这样保证的程序,特别是当您无法确定 nextInt() 的调用顺序时。

It is thread safe in the sense it will still generate random numbers when used by multiple threads.

The Sun/Oracle JVM implementation uses synchronized and AtomicLong as seed to improve consistency across threads. But it doesn't appear to be guarenteed across all platforms in the documentation.

I wouldn't write your program to require such a guarantee, especially as you cannot determine the order in which nextInt() will be called.

甜妞爱困 2024-11-11 08:17:53

它是线程安全的,尽管并非总是如此。

请参阅https://bugs.java.com/bugdatabase/view_bug?bug_id=6362070 了解更多详情。

It is thread safe, although it wasn't always.

See https://bugs.java.com/bugdatabase/view_bug?bug_id=6362070 for more details.

西瑶 2024-11-11 08:17:53

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

编辑:

不过,根据已接受的答案,自 Java 7 以来,文档似乎已经发生了变化,并且 Random 类似乎也提供了这种保证。

Acording to the Java 6 documentation, Math.random() guarantees it's safe for use by multiple threads. But the Random class does not. I would assume then you'll have to synchronize that yourself.

EDIT:

According to the accepted answer, though, the documentation seems to have changed since Java 7 and the Random class seems to offer that guarantee too.

心凉怎暖 2024-11-11 08:17:53

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

Yes, Random is thread safe. the nextInt() method calls the protected next(int) method which uses AtomicLong seed, nextseed (atomic long) to generate a next seed. AtomicLong is used for thread-safety upon seed generation.

月棠 2024-11-11 08:17:53

如上所述,它是线程保存的,但根据java.util.concurrent.ThreadLocalRandom可能是明智的random-java-util-concurrent-threadlocalrandom-multithreaded-environments/" rel="nofollow noreferrer">本文(链接已失效)。 ThreadLocalRandom也是Random的子类,因此它是向后兼容的。

文章链接比较了不同随机的分析结果
类:java.util.Random,java.util.concurrent.ThreadLocalRandom
和 java.lang.ThreadLocal。结果表明,
使用 ThreadLocalRandom 的性能最高,其次是
ThreadLocal 和性能最差的 Random 本身。

As said, it is thread save, but it may be wise to use java.util.concurrent.ThreadLocalRandom according to this article (link dead). ThreadLocalRandom is also a subclass of Random, so it is backwards compatible.

The article linked compared profiling results of the different Random
classes: java.util.Random, java.util.concurrent.ThreadLocalRandom
and java.lang.ThreadLocal<java.util.Random>. The results showed,
that the usage of ThreadLocalRandom is most performant, followed by
ThreadLocal and worst performing Random itself.

一身仙ぐ女味 2024-11-11 08:17:53

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

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

编辑2:OpenJDK 也使用 AtomicLong 作为种子。正如其他人所说,尽管依赖于此仍然不好。

There's no reason multiple threads can't all use the same Random. However, since the class is not explicitly thread-safe and maintains a sequence of pseudo-random numbers via the seed. Multiple threads may end up with the same random number. It would be better to create multiple Randoms for each thread and seed them differently.

EDIT: I've just noticed that the Sun implementation uses AtomicLong so i guess that is Thread-safe (as also noted by Peter Lawrey (+1)).

EDIT2: OpenJDK also uses AtomicLong for the seed. As others have said though it's still not good to rely on this.

慕烟庭风 2024-11-11 08:17:53

以下是我在不假设 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());
    }
};

Here's how I dealt with the problem without assuming that Random uses atomic variables. It can still randomly collide if currentTime * thread id is equal some time in the future, but that's rare enough for my needs. To truly avoid the possibility of collisions, you could have each request wait for a unique clock timestamp.

/**
 * 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());
    }
};
云雾 2024-11-11 08:17:53

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

The Random class is not set up for one instance to be used in multiple threads. Ofcourse, if you did this, likely you will increase the possibility of getting un-predictable and closer to random numbers. But since it is a pseudo-random generator, I cannot see why you would need to share an instance. Is there a more specific requirement?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文