【发布时间】:2010-11-30 12:00:05
【问题描述】:
SecureRandom 线程安全吗?也就是初始化之后,能否依赖对下一个随机数的访问是线程安全的?检查源代码似乎表明它是,this bug report 似乎表明它缺乏作为线程安全的文档是一个 javadoc 问题。有没有人确认它实际上是线程安全的?
【问题讨论】:
标签: java thread-safety
SecureRandom 线程安全吗?也就是初始化之后,能否依赖对下一个随机数的访问是线程安全的?检查源代码似乎表明它是,this bug report 似乎表明它缺乏作为线程安全的文档是一个 javadoc 问题。有没有人确认它实际上是线程安全的?
【问题讨论】:
标签: java thread-safety
请参阅 Java 9 中修复的 https://bugs.openjdk.java.net/browse/JDK-8165115。
上面写着:
SecureRandom对象可以安全地被多个并发使用 线程。SecureRandom服务提供商可以宣传它是 通过将服务提供者属性“ThreadSafe”设置为线程安全的 注册提供程序时为“true”。否则,SecureRandom类将同步访问以下SecureRandomSpi方法:SecureRandomSpi.engineSetSeed(byte[]),SecureRandomSpi.engineNextBytes(byte[]),SecureRandomSpi.engineNextBytes(byte[], SecureRandomParameters),SecureRandomSpi.engineGenerateSeed(int),和SecureRandomSpi.engineReseed(SecureRandomParameters).
【讨论】:
是的,是的。它扩展了Random,它总是有一个de facto线程安全实现,并且来自Java 7, explicitly guarantees threadsafety.
如果多个线程使用单个SecureRandom,则可能会出现争用影响性能的情况。另一方面,初始化SecureRandom 实例可能相对较慢。最好是共享一个全局 RNG,还是为每个线程创建一个新的 RNG,这取决于您的应用程序。 ThreadLocalRandom 类可用作提供支持SecureRandom 的解决方案的模式。
【讨论】:
SecureRandom 不仅会很慢,而且可能会因为缺少熵而挂起
SecureRandom 的当前实现是线程安全的,特别是 nextBytes(bytes[]) 和 setSeed(byte[]) 这两个变异方法是同步的。
好吧,据我所知,所有变异方法最终都通过这两种方法进行路由,SecureRandom 覆盖了Random 中的一些方法以确保这一点。哪个可行,但如果将来更改实施,可能会很脆弱。
最好的解决方案是先在SecureRandom 实例上手动同步。这意味着每个调用堆栈都会在同一个对象上获得两个锁,但这在现代 JVM 上通常非常便宜。也就是说,显式同步自己并没有太大的危害。例如:
SecureRandom rnd = ...;
byte[] b = new byte[NRANDOM_BYTES];
synchronized (rnd) {
rnd.nextBytes(b);
}
【讨论】:
java.security.SecureRandom#nextBytes 未同步。您能否指定您在哪个 Java 版本中找到了同步的#nextBytes?。