C#随机数生成器线程安全吗?
是c#'s rando> rando> rando> randy.next()
方法线程安全吗?
Is C#'s Random.Next()
method thread safe?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
是c#'s rando> rando> rando> randy.next()
方法线程安全吗?
Is C#'s Random.Next()
method thread safe?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(17)
有关线程安全的随机数生成器,请查看。从文档中:
For a thread safe random number generator look at RNGCryptoServiceProvider. From the docs:
我刚刚在螺纹上同时创建了随机实例,并从结果中获得了意外的模式,因为大概所有种子都是相同的。
我的解决方案是创建一个线程安全类 -
然后,为每个线程创建一个新的随机对象实例 -
I just created Random instance on a load of threads simultaneously and got unexpected patterns from the results because, presumably, all the seeds were the same.
My solution was to create a thread safe class -
And then, create a new Random object instance for each thread -
这是使用
threadlocal
的有效解决方案:要使用,替换:
与:
此解决方案已包装为 nuget软件包在
编辑:自.NET 6.0以来,您可以使用
randy.shared.next()
而不是使用。您仍然可以使用上述软件包,该软件包在上面的代码或随机
中使用预处理器指令。Here's an efficient solution using
ThreadLocal
:To use, replace:
With:
This solution has been packaged as a NuGet package with source available on GitHub.
EDIT: Since .NET 6.0 you can use
Random.Shared.Next()
instead. You can still use the above package which chooses between the above code orRandom.Shared
with preprocessor directives.这是 blueraja的答案作为静态课程的静态类,并实现了所有公共随机成员。
Here is an expanded version of BlueRaja's answer as a static class with comments and all public Random members implemented.
更新:不是。您需要在调用.next()方法时锁定某些“信号量”对象的每个连续调用的随机实例,或者在每个呼叫上使用具有保证随机种子的新实例。如Yassir所建议,您可以通过在.NET中使用密码学来获得保证的不同种子。
UPDATED: It is not. You need to either reuse an instance of Random on each consecutive call with locking some "semaphore" object while calling the .Next() method or use a new instance with a guaranteed random seed on each such call. You can get the guaranteed different seed by using cryptography in .NET as Yassir suggested.
传统 thread nore noreferrer“> thread thread local Storage方法可以是通过对种子使用无锁算法来改进。以下是从Java的算法中毫无耻辱的(甚至可能上):
The traditional thread local storage approach can be improved upon by using a lock-less algorithm for the seed. The following was shamelessly stolen from Java's algorithm (possibly even improving on it):
不,使用来自多个线程的同一实例会导致其破裂并返回所有0。但是,创建线程安全版本(无需在每个调用
next()
)的无需讨厌的锁。改编自本文:这个想法是为每个线程保留一个单独的
static Random
变量。但是,以明显的方式执行此操作会失败,因为Random
的另一个问题 - 如果在几乎同一时间创建了多个实例(在约15ms之内),它们将全部返回相同的值!为了解决此问题,我们创建一个全球静态随机
实例,以生成每个线程使用的种子。顺便说一句,上面的文章具有
随机
的这两个问题的代码。No, using the same instance from multiple threads can cause it to break and return all 0's. However, creating a thread-safe version (without needing nasty locks on every call to
Next()
) is simple. Adapted from the idea in this article:The idea is to keep a separate
static Random
variable for each thread. Doing that in the obvious way fails, however, because of another issue withRandom
- if multiple instances are created at nearly the same time (within about 15ms), they will all return the same values! To fix this, we create a globally-staticRandom
instance to generate the seeds used by each thread.The above article, by the way, has code demonstrating both of these issues with
Random
.下一个
方法可以实现线程安全性。但是,这是一种实例方法。如果您不在不同线程上共享随机
的实例,则不必担心一个实例中的状态腐败。请勿在不同的线程上使用随机
的单个实例,而不会持有某种独有的锁定。乔恩·斯基特(Jon Skeet)在此主题上有几个不错的帖子:
staticrandom
staticrandom 一个>重新审视随机性
正如某些评论员所指出的使用
随机
的不同实例,这些实例是线程排名,但被播种相同,因此会诱导伪数字的相同序列,因为它们可以同时或在彼此之间紧密的时间近处创建。减轻该问题的一种方法是使用主随机
实例(由单个线程锁定)来生成一些随机种子并初始化新的随机>随机
其他每个线程的实例使用。There's nothing special done in the
Next
method to achieve thread safety. However, it's an instance method. If you don't share instances ofRandom
across different threads, you don't have to worry about state corruption within an instance. Do not use a single instance ofRandom
across different threads without holding an exclusive lock of some sort.Jon Skeet has a couple nice posts on this subject:
StaticRandom
Revisiting randomness
As noted by some commentators, there is another potential problem in using different instances of
Random
that are thread-exclusive, but are seeded identically, and therefore induce the identical sequences of pseudorandom numbers, because they may be created at the same time or within close temporal proximity of each other. One way to alleviate that issue is to use a masterRandom
instance (which is locked by a single thread) to generate some random seeds and initialize newRandom
instances for every other thread to use.微软的官方答案是非常 strong no 。来自 http://msdn.microsoft.com/en-en-us/en-en-us/ library/system.random.aspx#8 :
如DOC中所述由多个线程使用:它只是停止工作。
(即,有一个种族条件,当触发时,从“ andural.next ....”的返回值对于所有后续调用的方法为0。)
The offical answer from Microsoft is a very strong no. From http://msdn.microsoft.com/en-us/library/system.random.aspx#8:
As described in the docs, there is a very nasty side effect that can happen when the same Random object is used by multiple threads: it just stops working.
(i.e. there is a race condition which when triggered, the return value from the 'random.Next....' methods will be 0 for all subsequent calls.)
如前所述,Anwer是 no 。但是,从 .net6 开始,我们有盒子线程安全替代方案:
randy.shared.next();
请参阅此处的详细信息。
As was written before, anwer is No. However, starting from .NET6, we have out of box thread-safe alternative:
Random.Shared.Next();
See details here.
不,这不是线程的安全。如果您需要使用不同线程的相同实例,则必须同步使用情况。
不过,我真的看不到您需要的原因。每个线程具有自己的随机类实例将更加有效。
No, it's not thread safe. If you need to use the same instance from different threads, you have to synchronise the usage.
I can't really see any reason why you would need that, though. It would be more efficient for each thread to have their own instance of the Random class.
另一种安全方法是使用
threadlocal< t>
如下:generateSeed()
方法将需要每次调用唯一值以确保随机返回一个唯一值每个线程中的数字序列都是唯一的。将适用于少量线程。
Another thread safe way is to use
ThreadLocal<T>
as follows:The
GenerateSeed()
method will need to return a unique value each time it is called to assure that the random number sequences are unique in each thread.Will work for small numbers of threads.
更新从.net 6 在窗帘后面进行同步)。
使用
threadlocal
:Update Starting from .NET 6 Random.Shared provides a built-in thread-safe
Random
type (usingThreadStatic
behind the curtains for synchronization) .Original Answer Reimplementation of BlueRaja's answer using
ThreadLocal
:就其价值而言,这里是继承
Random
的线程安全性强的RNG。该实现包括静态输入点,易于使用,它们的名称与公共实例方法相同,但前缀为“ get”。
调用
rngcryptoserviceprovider.getbytes
是一个相对昂贵的操作。通过使用内部缓冲区或“池”来减少这种方法,以使rngcryptoserviceprovider
更有效地使用频率。如果应用程序域中几代人几代,则可以将其视为开销。For what its worth, here is a thread-safe, cryptographically strong RNG that inherits
Random
.The implementation includes static entry points for ease of use, they have the same names as the public instance methods but are prefixed with "Get".
A call to the
RNGCryptoServiceProvider.GetBytes
is a relatively expensive operation. This is mitigated through the use of an internal buffer or "Pool" to make less frequent, and more efficient use ofRNGCryptoServiceProvider
. If there are few generations in an application domain then this could be viewed as overhead.由于
随机
不是线程安全,因此您应该每个线程一个,而不是全局实例。如果您担心这些多个随机
同时播种的类(即dateTime.now.ticks
之类的),则可以使用guid < /code> s播种每个。 .NET
GUID
生成器的长度相当长以确保不可重复的结果,因此:Since
Random
isn't thread-safe, you should have one per thread, rather than a global instance. If you're worried about these multipleRandom
classes being seeded at the same time (i.e. byDateTime.Now.Ticks
or such), you can useGuid
s to seed each of them. The .NETGuid
generator goes to considerable lengths to ensure non-repeatable results, hence:每个文档
http://msdn.microsoft.com/en-en-us/library/ system.random.aspx
Per documentation
http://msdn.microsoft.com/en-us/library/system.random.aspx
这是一个简单的解决方案,不涉及创建类。隐藏了临时Lambda中的所有内容:
在需要线程安全的随机生成器定义的任何类中
,然后在类中自由使用:
Radndom函数可以根据所需的内容具有不同的签名。例如
Here is a simple solution that doesn't involve creating classes. Hides everything inside an ad-hoc lambda:
In any class that needs a thread safe random generator define
Then use it freely inside your class:
The radndom function can have different signatures depending what is needed. e.g.