SecureRandom 线程安全吗?

Posted

技术标签:

【中文标题】SecureRandom 线程安全吗?【英文标题】:Is SecureRandom thread safe? 【发布时间】:2010-11-30 12:00:05 【问题描述】:

SecureRandom 线程安全吗?也就是初始化之后,能否依赖对下一个随机数的访问是线程安全的?检查源代码似乎表明它是,this bug report 似乎表明它缺乏作为线程安全的文档是一个 javadoc 问题。有没有人确认它实际上是线程安全的?

【问题讨论】:

【参考方案1】:

请参阅 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).

【讨论】:

【参考方案2】:

是的,是的。它扩展了Random,它总是有一个de facto线程安全实现,并且来自Java 7, explicitly guarantees threadsafety.

如果多个线程使用单个SecureRandom,则可能会出现争用影响性能的情况。另一方面,初始化SecureRandom 实例可能相对较慢。最好是共享一个全局 RNG,还是为每个线程创建一个新的 RNG,这取决于您的应用程序。 ThreadLocalRandom 类可用作提供支持SecureRandom 的解决方案的模式。

【讨论】:

感谢您的更新。奇怪的是,该错误被标记为“将无法修复”。但他们还是修好了。哦,好吧,我不羡慕他们的错误数据库的大小。 初始化SecureRandom 不仅会很慢,而且可能会因为缺少熵而挂起 请记住 ThreadLocalRandom 非常容易破解,所以如果您打算将生成的值暴露给世界,请使用 SecureRandom 代替 jazzy.id.au/default/2010/09/20/… 我要在这里站出来说这个答案是不正确的。保证线程安全的 Random 契约对子类没有约束力。当然,记录的 Random 的所有其他属性都没有绑定到子类,所以我不明白为什么应该假设线程安全。 @JamesKPolk 未能保留超类型的属性将违反可替换性原则。【参考方案3】:

SecureRandom 的当前实现是线程安全的,特别是 nextBytes(bytes[])setSeed(byte[]) 这两个变异方法是同步的。

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

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

    SecureRandom rnd = ...;

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

【讨论】:

至少在 JDK 10 中,SecureRandom 是基于提供程序的,并检查提供程序是否是线程安全的,如果不是,则仅在 nextBytes 中同步。 Java 8 中的 java.security.SecureRandom#nextBytes 未同步。您能否指定您在哪个 Java 版本中找到了同步的#nextBytes?。

以上是关于SecureRandom 线程安全吗?的主要内容,如果未能解决你的问题,请参考以下文章

java priorityblockingqueue 线程安全吗

mongodatabase mongocollection 线程安全吗

可以从多个线程等待相同的任务 - 等待线程安全吗?

可以从多个线程等待相同的任务 - 等待线程安全吗?

Java+线程内部调用实例方法会多线程安全吗?

lib 魔法线程安全吗?