java.util.UUID在多线程环境下是安全的吗?

30
我提出这个问题是基于以下观察。
在高度多线程环境中的线程转储中获取此堆栈跟踪 “http-80-200”守护程序优先级=10 tid=0x00002aaab4981000 nid=0x7520等待获取监视器入口[0x000000004fec7000] java.lang.Thread.State: BLOCKED(在对象监视器上) 在java.security.SecureRandom.nextBytes(SecureRandom.java:433)处 - 等待锁<0x00000000c00da220>(一个java.security.SecureRandom) 在java.util.UUID.randomUUID(UUID.java:162)处
找到此链接 https://bugs.java.com/bugdatabase/view_bug?bug_id=6611830 如果UUID不是线程安全的,请提供其他库(如果存在的话)的建议。

4
线程处于BLOCKED状态本身并不意味着存在问题。如果线程正在等待获取同步方法或代码块的锁定,则这是正常的。只有当线程永远停留在此状态时才可能表示存在死锁问题。 - Jesper
请为链接点赞(由Josh Bloch提出的错误报告...)-还有,正如错误报告中链接的那样(http://cr.openjdk.java.net/~mduigou/6611830/webrev.0/webrev/),这个错误应该已经被修复了。 - Mr_and_Mrs_D
1个回答

17

UUID是不可变的,因此它可能是线程安全的,但显然在一些访问器中存在一些邪恶缓存会使其不安全(该漏洞现已修复)。

但是,您的线程转储只是说明一个线程正在等待SecureRandom.nextBytes锁定,该锁用于UUID.randomUUID工厂,这绝对是线程安全的。据我所知,这是多个线程同时调用它时应该发生的情况。


使用SecureRandom在某些情况下会使此方法非常缓慢。如果您真的想要最好的位,那么使用此位源是很好的选择,但如果您需要许多UUID(例如用于模拟),则可能会非常慢。 - Ted Dunning
2
由于这个漏洞已经在几年前修复了,所以这个答案是否应该说它现在是线程安全的? - eis
至少在Java 11中似乎是线程安全的。您可以调查java.security.SecureRandom中的实现,其中方法nextBytes()是在基础随机数生成器中未启用同步时添加同步的方法。 - Dmitry Pukhov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接