我对线程和并发相当缺乏经验;为了解决这个问题,我目前正致力于在 F# 中实现随机搜索算法。我遵循现有 C# 示例的想法,围绕 System.Random 类编写了一个包装器 - 但由于我不确定如何开始对其错误行为进行单元测试,所以我想听听更有经验的人怎么说,如果我的代码有明显的缺陷或改进,无论是由于 F# 语法还是线程误解:
open System
open System.Threading
type Probability() =
static let seedGenerator = new Random()
let localGenerator =
new ThreadLocal<Random>(
fun _ ->
lock seedGenerator (
fun _ ->
let seed = seedGenerator.Next()
new Random(seed)))
member this.Draw() =
localGenerator.Value.NextDouble()
我对此的理解是:ThreadLocal 确保对于一个实例,每个线程接收自己的 Random 实例,并由公共静态 Random 提供自己的随机种子。这样,即使该类的多个实例在很短的时间内创建,它们也会收到自己的种子,从而避免“重复”随机序列的问题。该锁强制任何两个线程都不会获得相同的种子。
这看起来正确吗?有明显的问题吗?
我认为你的方法非常合理 - 使用ThreadLocal
让您安全地访问Random
并使用master提供种子的随机数生成器意味着即使您同时从多个线程访问它,您也会获得随机值。从加密意义上来说,它可能不是随机的,但对于大多数其他应用程序来说应该没问题。
至于测试,这是相当棘手的。如果Random
中断时,它会一直返回 0,但这只是经验,很难说你需要继续不安全地访问它多长时间。我能建议的最好的事情是实施一些简单的随机性测试(一些维基百科上有简单的 http://en.wikipedia.org/wiki/Statistical_randomness#Tests)并从循环中的多个线程访问您的类型 - 尽管这仍然是一个非常糟糕的测试,因为它可能不会每次都失败。
除此之外,你不需要使用type
来封装这种行为。它也可以写成一个函数:
open System
open System.Threading
module Probability =
let Draw =
// Create master seed generator and thread local value
let seedGenerator = new Random()
let localGenerator = new ThreadLocal<Random>(fun _ ->
lock seedGenerator (fun _ ->
let seed = seedGenerator.Next()
new Random(seed)))
// Return function that uses thread local random generator
fun () ->
localGenerator.Value.NextDouble()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)