SecureRandom线程安全吗?


103

SecureRandom线程安全的?也就是说,在对其进行初始化之后,能否依靠下一个随机数来确保线程安全?检查源代码似乎表明事实确实如此,并且此错误报告似乎表明其缺乏作为线程安全的文档是javadoc的问题。有没有人确认它实际上是线程安全的?

Answers:


108

是的。它扩展了Random,始终具有事实上的线程安全实现,从Java 7开始,它明确地保证了线程安全。

如果许多线程使用单个SecureRandom,则可能存在争用,从而影响性能。另一方面,初始化SecureRandom实例可能相对较慢。共享全局RNG还是为每个线程创建一个新的RNG取决于您的应用程序。的ThreadLocalRandom类可以被用作图案,以提供一个解决方案,支持SecureRandom


3
感谢更新。奇怪的是,该错误被标记为“无法修复”。但是他们还是解决了。哦,好吧,我不羡慕他们的bug数据库。
Yishai

4
初始化a SecureRandom不仅很慢,而且可能会由于缺少熵而挂起
Walter Tross 2014年

8
请记住,ThreadLocalRandom是很容易被破解,因此如果您计划生成的值暴露给世界,使用的SecureRandom替代jazzy.id.au/default/2010/09/20/...
walv

2
我要在这里走出去,说这个答案不正确。保证线程安全的Random合同对子类没有约束。当然,随机记录的所有其他属性都不会绑定到子类上,因此我不明白为什么应该假定线程安全。
总统詹姆斯·波克(James K. Polk)

2
@JamesKPolk无法保留超类型的属性会违反可替换性原则。
erickson '18

11

的当前实现SecureRandom是线程安全的,尤其是两种变异方法nextBytes(bytes[])并且setSeed(byte[])是同步的。

好吧,据我所知,所有变异方法最终都会通过这两种方法进行路由,并SecureRandom覆盖其中的一些方法Random以确保实现这一点。哪个可行,但如果将来更改实现,可能会很脆弱。

最好的解决方案是先在SecureRandom实例上手动同步。这意味着每个调用堆栈将在同一对象上获取两个锁,但是在现代JVM上通常非常便宜。也就是说,显式同步自己没有太大的危害。例如:

    SecureRandom rnd = ...;

    byte[] b = new byte[NRANDOM_BYTES];
    synchronized (rnd) {
        rnd.nextBytes(b);
    }

3
至少在JDK 10中,SecureRandom基于提供程序,并检查提供程序是否是线程安全的,仅在nextBytes中进行同步(如果不是)。
nafg

java.security.SecureRandom#nextBytesJava 8中未同步。您能否指定在哪个Java版本中找到了同步的#nextBytes?。
Jaime Hablutzel
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.