【问题标题】:Random number same in different processes [duplicate]不同进程中的随机数相同[重复]
【发布时间】:2020-02-20 20:17:58
【问题描述】:

我正在使用以下代码生成一个唯一的应用程序实例 ID 用于日志记录。

public MainWindow()
{
    InitializeComponent();

    Random rnd = new Random();

    instanceID = rnd.Next(100000, 999999);

    /// ...
}

我的应用程序从 windowsserver 开始,作为不同的服务(使用 nssm)2 次或更多次具有不同的参数。 我的问题:如果它们同时开始(同一秒),则 instanzID 相同,如果 1 秒或更多秒的差异 instanzID 不同。 我怎样才能避免这种情况?

【问题讨论】:

  • "生成唯一的应用程序实例ID" - 语义很重要。 “随机”和“独特”是两个截然不同的东西。也许改用Guid
  • 谢谢,我改成Guid.NewGuid,下次测试一下

标签: c# random


【解决方案1】:

好吧,Random 不是 线程安全(你提到了“服务器作为不同的服务”),这就是为什么让每个线程都有自己的Random实例:

private static ThreadLocal<Random> MyRandom = ...

由于我们不希望所有这些实例生成相同序列,让我们提供一个熵源,我们可以在RNGCryptoServiceProvider的帮助下做到这一点:

using System.Security.Cryptography;
using System.Threading;

...  

private static ThreadLocal<Random> MyRandom = new ThreadLocal<Random>(() => {
  int seed;

  using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider()) {
    byte[] seedData = new byte[sizeof(int)];

    provider.GetBytes(seedData);

    seed = BitConverter.ToInt32(seedData, 0);
  }

  return new Random(seed);
});

现在,MyRandom线程安全的,每个线程都有自己的(伪)随机序列。

instanzID = MyRandom.Next(100000, 999999);

【讨论】:

  • 我认为问题不在于使用来自不同线程的相同 Random 实例。问题是在不同进程中同时实例化的独立Random 实例可以使用相同的值播种。使用RNGCryptoServiceProvider 播种是一种解决方案,但我认为ThreadLocal 与OP 的问题无关。
  • 是的,canton7 是对的,我编辑了这个问题以便更好地理解。
【解决方案2】:

默认情况下,Random 对象使用当前时间作为初始种子。要做你想做的事,只需在构造函数中提供一个int 作为Random rnd = new Random(seed) 其中seed 是算法的初始种子。只要seed 与您的所有Random 对象相同,它们就会产生相同的随机数序列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-29
    • 2013-01-18
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    相关资源
    最近更新 更多