Random 类线程安全吗?
在多个线程之间共享 Random 类的一个实例是否有效?特别是从多个线程调用 nextInt(int)
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
在多个线程之间共享 Random 类的一个实例是否有效?特别是从多个线程调用 nextInt(int)
?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(8)
它是线程安全的,因为当多个线程使用时它仍然会生成随机数。
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.它是线程安全的,尽管并非总是如此。
请参阅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.
根据 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.
是的,随机是线程安全的。
nextInt()
方法调用受保护的next(int)
方法,该方法使用AtomicLong seed, nextseed
(原子长)生成下一个种子。使用AtomicLong
用于种子生成时的线程安全。Yes, Random is thread safe. the
nextInt()
method calls the protectednext(int)
method which usesAtomicLong seed, nextseed
(atomic long) to generate a next seed.AtomicLong
is used for thread-safety upon seed generation.如上所述,它是线程保存的,但根据java.util.concurrent.ThreadLocalRandom可能是明智的random-java-util-concurrent-threadlocalrandom-multithreaded-environments/" rel="nofollow noreferrer">本文(链接已失效)。 ThreadLocalRandom也是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.多个线程没有理由不能全部使用相同的随机数。但是,由于该类不是显式线程安全的,并且通过种子维护伪随机数序列。多个线程可能会得到相同的随机数。最好为每个线程创建多个随机数并以不同的方式播种它们。
编辑:我刚刚注意到 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.
以下是我在不假设 Random 使用原子变量的情况下处理该问题的方法。如果
currentTime * thread id
在未来某个时间相等,它仍然可能随机碰撞,但这对于我的需求来说是很少见的。为了真正避免冲突的可能性,您可以让每个请求等待唯一的时钟时间戳。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.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?