gpt4 book ai didi

java - 线程安全警告

转载 作者:行者123 更新时间:2023-11-29 06:35:48 25 4
gpt4 key购买 nike

我在大型分布式 Scala 和 Akka 应用程序中使用 org.apache.commons.math3.distribution.NormalDistribution。在调试过程中,我发现 sample() 偶尔会返回 NaN,它会无声传播并导致线程在 org.apache.commons.math3.ode.nonstiff.DormandPrince853Integrator/中挂起p>

NaN 可以简单地用并行集合重现(不会发生在顺序代码中):

val normal = new NormalDistribution(0,0.1)
(1 to 1000000000).par.foreach{i =>
val r = normal.sample
if(r.isNaN()) throw new Exception("r = "+r)
}

显然,在 foreach 中移动 val normal 解决了这种情况下的问题。

我看过 docs但看不到任何警告我此类问题的信息。我是否没有掌握有关线程安全的更基本概念?不用说,我现在正在检查 NaN。

最佳答案

通过 digging through sources你会发现这个构造函数使用了Well19937c随机生成器,乍一看它本身并不是线程安全的。

您可以通过将数字生成器显式设置为 SynchronizedRandomGenerator 使其成为线程安全的它包装了任何其他随机数生成器(如 Well19937cMersenne Twister)。请注意,通过使用 SynchronizedRandomGenerator 同步对随机数生成器的访问,您将失去所有潜在的性能优势,并且由于同步,“并行”版本可能比顺序版本慢。另一方面,在每次并行迭代中重新初始化随机分布可能会根据当前时间用相似的值多次重新播种 PRNG,因此您的结果会出现偏差。

一个非常普遍的经验法则(如果我在这里错了,请纠正我)是 99% 的时间,除非另有明确说明,否则在做任何依赖于随机的事情时,你应该坚持顺序执行数字生成,因为通常 PRNG 会存储状态,当从多个线程调用它们时可能会损坏这些状态。除非您之后进行昂贵的计算,否则同步(在线程安全的有状态 PRNG 的情况下)将成为瓶颈。

关于java - 线程安全警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20969292/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com