C# 这个静态随机类是线程安全的吗?

C# 这个静态随机类是线程安全的吗?,c#,multithreading,asynchronous,thread-safety,C#,Multithreading,Asynchronous,Thread Safety,我正在编写的程序是一个游戏服务器,它将在不同的线程中有多个会话。为了避免不必要的锁等待时间,添加了[ThreadStatic] 该程序将包括一些异步函数和 ThreadSafeStaticRNG(此类)将在异步中使用 public class ThreadSafeStaticRNG { [ThreadStatic] static Random r = new Random(); /// <summary> /// get random number

我正在编写的程序是一个游戏服务器,它将在不同的线程中有多个会话。为了避免不必要的锁等待时间,添加了
[ThreadStatic]

该程序将包括一些异步函数和
ThreadSafeStaticRNG
(此类)将在异步中使用

public class ThreadSafeStaticRNG 
{
    [ThreadStatic]
    static Random r = new Random();

    /// <summary>
    /// get random number from [min,max)
    /// </summary>
    /// <returns></returns>
    public static int GetNext(int min, int max)
    {
        int n;
        lock (r)
        {
            n = r.Next(min, max);
        }
        return n;
    }
}
public类ThreadSafeStaticRNG
{
[线程静态]
静态随机r=新随机();
/// 
///从[最小值,最大值]中获取随机数
/// 
/// 
公共静态int-GetNext(int-min,int-max)
{
int n;
锁(右)
{
n=r.Next(最小值,最大值);
}
返回n;
}
}
我需要验证

  • 据我所知,使用
    async
    /
    Task
    创建的工作线程不会有单独的
    ThreadStatic
    实例。因此需要锁定
  • 如果上述为真,则
    lock
    中的唯一限制是
    await
    不能用于
    lock
    。因此在
    异步函数中使用
    lock
    是安全的
  • (编辑)
    lock(r)
    对于
    r
    实例,可以吗?我查看的官方文档和其他代码仅为
    lock
    创建了其他
    对象
  • 显示的代码(过度)线程安全且不正确(可能生成相同/同步的随机值)

    保证每个线程(手动创建或从线程池中获取)都有自己的变量实例。因此,只要不在外部公开该变量(如代码中所示),就不需要
    锁定该变量

    每一时刻的每个线程只能运行一个函数——无论是代码< >异步> <代码>方法或函数传递给线程。线程不会在执行中间的函数之间切换,因此不能同时调用两个调用<代码> GETNest同时在同一线程上。

    请注意,快速创建多个
    Random
    对象可能会导致-请检查此特定项以正确初始化此类每线程实例
    Random
    (使用增量种子)

  • 任务/异步可能没有为其分配单独的线程,并且一个任务可能在多个线程上执行
  • 是的,它可以安全地使用锁,并且具有非线程安全的随机性 函数,这是必需的。不需要将锁和 在我的应用程序中使用Lock()的意图更为明显 意见,并停止线程静态
  • 创建一个新对象并对其进行锁定是正常的,而不是对操作对象进行锁定,但在您的情况下,这样做并不是不正确的

  • 也许更好的模式是反转问题,让调用者将一个新Random()对象的实例传递到依赖它的代码中。这将保证每个任务都有一个唯一的Random实例,并且更具声明性和可测试性(通过IRandom并在单元测试区使用测试替代品将是最好的整体解决方案。)-对于单元测试,您需要的是可预测的结果,而不是随机结果,因此通过IOC用已知数字生成器替换随机数字生成器的能力将非常重要。

    @UweKeim是的,我做了研究,对两个问题没有明确的答案。这就是为什么我说
    我需要验证
    ,因为信息不是来自ficial文档。我的错,没有把你的问题读得足够好,对不起。对不起,我没有读完整的答案。所以,在这种情况下,
    async
    将有独立的
    RNG
    ,锁是完全不必要的,对吗?@YukiNyaa我强烈怀疑你需要阅读…是的,锁是不必要的。“在这种情况下,异步将有独立的RNG”没有答案-链接搜索应该能够帮助您解决这个问题未执行预期的操作。请参阅,其中的注释说明:不要为标记为ThreadStaticAttribute的字段指定初始值,因为此类初始化仅在类构造函数执行时发生一次,因此仅影响一个线程。如果未指定初始值,则可以依赖初始化为的字段如果它是一个值类型,或者它是一个引用类型,则它的默认值。谢谢。我应该考虑使用RNG本身不同的方法。