Random类在C#中非线程安全,多线程共享实例会导致状态损坏、重复值等问题;推荐使用ThreadLocal实现线程隔离,或加锁同步访问,高安全性场景可用RandomNumberGenerator。

在C#中,Random 类不是线程安全的。如果多个线程同时访问同一个 Random 实例,可能会导致内部状态损坏,甚至返回 0 或重复值。尤其在多线程环境中,比如并行循环或任务并行库(TPL)场景下,这个问题尤为明显。
问题根源:共享 Random 实例导致竞争条件
当多个线程共用一个 Random 实例时,它们可能同时调用 Next() 方法。由于 Random 内部使用共享的状态字段(如 seed),多线程读写这些字段会造成数据竞争,最终可能导致:
- 生成大量相同的随机数
- 性能下降或程序挂起
- 极少数情况下引发异常
解决方案1:每个线程使用独立的 Random 实例
最常见且高效的做法是为每个线程创建独立的 Random 实例,避免共享。可以使用 ThreadLocal
private static readonly ThreadLocal<Random> _random
= new ThreadLocal<Random>(() => new Random(Guid.NewGuid().GetHashCode()));
登录后复制
使用方式:
int randomNumber = _random.Value.Next(1, 100);
登录后复制
说明: 使用 Guid.NewGuid().GetHashCode() 提供不同的种子,避免多个线程因同时初始化而获得相同种子的问题。DateTime.Now.Ticks 作为种子在高并发下不可靠,应避免。
解决方案2:使用锁(Lock)同步访问
如果必须共享 Random 实例,可以通过加锁保证线程安全:
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~