如何制作 ac# 线程安全的随机数生成器

mas*_*nix 3 c# multithreading .net-core

我的代码中有一个循环

Parallel.For(0, Cnts.MosqPopulation, i => { DoWork() });
Run Code Online (Sandbox Code Playgroud)

但是在DoWork()函数中,有多个对随机数生成器的调用,其定义如下:

public static class Utils
{
    public static readonly Random random = new Random();

}
Run Code Online (Sandbox Code Playgroud)

它是静态实例,因此只播种一次。我可以在整个代码中使用它。

根据 MSDN 和其他 stackoverflow 线程,这不是线程安全的。事实上,我注意到有时我的代码会中断并且随机数生成器开始生成全零(根据 MSDN 文档)。

还有其他的 stackoverflow 线程,但是比较老,而且实现速度很慢。我不能在生成数字上浪费时间,因为该程序是一项科学计算,并且正在运行数百次模拟。

我从 2.0 天开始就没有使用过 .net,我不确定该语言是如何演变成能够制作快速、高效、线程安全的 RNG。

以下是之前的主题:

C# 随机数生成器线程安全吗?

在多线程应用程序中使用 Random 的正确方法

用于 C# 的快速线程安全随机数生成器

注意:因为我需要一个快速的实现,所以我不能使用RNGCryptoServiceProvider相当慢的。

注2:我没有最少的工作代码。我什至不知道从哪里开始,因为我不知道线程安全是如何工作的,也不知道 C# 的高级知识。所以看起来我确实在要求一个完整的解决方案。

Flo*_*yon 5

使用ThreadStatic属性和自定义 getter,您将获得Random每个线程的单个实例。如果这是不可接受的,请使用锁。

public static class Utils
{
    [ThreadStatic]
    private static Random __random;

    public static Random Random => __random??(__random=new Random());
}
Run Code Online (Sandbox Code Playgroud)

ThreadStatic属性不会在每个线程上运行初始化程序,因此您有责任在访问器中执行此操作。还要考虑一下您的种子初始值设定项,您可以使用类似的东西

new Random((int) ((1+Thread.CurrentThread.ManagedThreadId) * DateTime.UtcNow.Ticks) )
Run Code Online (Sandbox Code Playgroud)