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本身不同的方法。