以线程安全的方式获取随机数

Ale*_*kov 7 .net c# random multithreading thread-safety

这是一篇很好的文章,描述了随机数的线程安全性:以线程安全的方式获取随机数

但我坚持使用"RandomGen2"示例:

public static class RandomGen2 
{ 
    private static Random _global = new Random(); 
    [ThreadStatic] 
    private static Random _local;

    public static int Next() 
    { 
       Random inst = _local; 
       if (inst == null) 
       { 
           int seed; 
           lock (_global) seed = _global.Next(); 
           _local = inst = new Random(seed); 
       } 
       return inst.Next(); 
   } 
Run Code Online (Sandbox Code Playgroud)

}

为什么线程静态字段被复制到局部变量:Random inst = _local; ?为什么不简单地使用

if (_local == null) .... return _local.Next()

Jon*_*eet 10

注意:自写这个答案以来,我已经意识到创建多个Random实例的问题,即使它听起来应该有效.我一般都发现,更好的选择是拥有一个Random实例并锁定它.虽然这是一个潜在的瓶颈,但在大多数应用中它不会引起问题.


我怀疑这只是为了避免多次读取线程静态变量的成本.这是相对低效的话,用阅读的局部变量进行比较.

你的建议会奏效,但效率会略低一些.在其他情况下,值可能会在读取之间发生变化 - 当然,在这种情况下,这不是问题,因为它是线程局部变量.

使用.NET 4及更高版本,这可以更简单地使用ThreadLocal<T>:

public static class RandomGen2 
{ 
    private static Random _global = new Random(); 
    private static ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
    {
        int seed;
        lock (_global) seed = _global.Next();
        return new Random(seed);
    });


    public static int Next() 
    { 
        return _local.Value.Next();
    } 
}
Run Code Online (Sandbox Code Playgroud)


Evg*_*eny 5

.NET6Random开始,有开箱即用的线程安全:

var rndIntValue = Random.Shared.Next();
Run Code Online (Sandbox Code Playgroud)

查看具体信息