如何制作一个C#线程安全的随机数生成器 [英] how to make a c# thread-safe random number generator

查看:87
本文介绍了如何制作一个C#线程安全的随机数生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码中有一个循环

Parallel.For(0, Cnts.MosqPopulation, i => { DoWork() });

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

however in the DoWork() function, there are multiple calls to a random number generator which is defined as follows:

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

}

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

It's static instance so that it is only seeded once. And I can use it throughout the code.

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

According to MSDN and other stackoverflow threads, this is not threadsafe. Infact, I have noticed at sometimes my code breaks and the random number generator starts generating all zeros (as per the MSDN documentation).

还有其他stackoverflow线程,但是它们比较旧并且实现速度很慢.由于程序是科学计算并且正在运行数百个模拟,因此我不能浪费时间来生成数字.

There are other stackoverflow threads, but are rather old and the implementation is slow. I can't afford to lose time on generating the numbers as the program is a scientific computation and is running hundreds of simulations.

自2.0天以来,我一直没有使用.net,而且我不确定该语言的发展方式是否能够生成快速,高效,线程安全的RNG.

I havn't worked with .net since the 2.0 days and I am not sure how the language has evolved to be able to make a fast, efficient, thread-safe RNG.

以下是先前的主题:

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

在多线程应用程序中正确使用随机数的方法

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

注意:因为我需要快速的实现,所以我不能使用速度很慢的RNGCryptoServiceProvider.

Note: because I need a fast implementation, I can not use the RNGCryptoServiceProvider which is rather slow.

注2:我没有最低限度的工作代码.我什至不知道从哪里开始,因为我不知道线程安全性是如何工作的,或者不了解c#.因此,似乎我正在寻求一个完整的解决方案.

Note2: I don't have a minimal working code. I don't even know where to begin as I don't know how thread-safety works or have high level knowledge of c#. So it does seem like I am asking for a complete solution.

推荐答案

使用ThreadStatic属性和自定义的getter,您将在每个线程中获得一个Random实例.如果不能接受,请使用锁.

Using the ThreadStatic attribute and a custom getter, you will get a single Random instance per thread. If this is not acceptable, use locks.

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

    public static Random Random => __random??(__random=new Random());
}

ThreadStatic属性不会在每个线程上运行初始化程序,因此您有责任在访问器中运行初始化程序.另外考虑一下您的种子初始化程序,您可以使用类似

The ThreadStatic attribute does not run the initializer on each thread so you are responsible for doing so in your accessor. Also think about your seed initializer, you can use something like

new Random((int) ((1+Thread.CurrentThread.ManagedThreadId) * DateTime.UtcNow.Ticks) )

这篇关于如何制作一个C#线程安全的随机数生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆