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

查看:35
本文介绍了如何制作一个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# 随机数生成器线程安全吗?

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

用于 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天全站免登陆