Random.Next()仅适用于受限制的时间/调用次数?

时间:2018-04-06 21:54:56

标签: c# random

我一直在使用永远运行的代码"在一个类中使用静态随机。一切正常,数字是随机的,没有问题...限制时间(或调用次数,不确定)。一段时间后,它开始始终生成相同的数字。

以下是问题:您是否知道随机课程的时间限制?你有过这样的问题吗?

我已经更改了代码,如果有帮助的话,我现在会在一两个星期内(每x分钟创建一个新对象),但我想知道什么是'在这背后,我将来应该更加小心。

好的......小小的更新:

不,它不是关于多线程的,它可以在很长一段时间内工作(比如一周左右),之后它只会一直返回一个数字。

private static Random random = new Random();

public static string GetRandomString(int length)
{
    const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    return new string(Enumerable.Repeat(chars, length)
        .Select(s => s[random.Next(s.Length)]).ToArray());
}

"时间" (不知道多久)它开始全部返回相同的字符串。如上所述:它不是多线程的问题,因为它继续返回相同的值#34;永远"。

1 个答案:

答案 0 :(得分:2)

行, 让我们总结一下

  1. 是的,使用多线程访问来访问该随机数。这似乎不是一个问题,因为随机文本被返回,即使返回了一些不是问题的双重文本(不应该发生)
  2. 随机和多线程的问题不是人们用来说的话:"不要这样做,因为它可以返回相同的值",原因是(Evk在聊天中提到) )随机的内部状态导致失败"随机性"随机甚至打破造成上述故障的物体(一直返回0)

  3. 如果你仍然不相信或只是想知道"它是如何运作的......" (就像我想的那样)你有时间阅读......你走了: 在Random类里面有一个数组

    private int [] SeedArray = new int [56];

  4. 当使用任何Next方法时,会有一个始终调用的InternalSample方法,它看起来像:

     private int InternalSample()
        {
          int inext = this.inext;
          int inextp = this.inextp;
          int index1;
          if ((index1 = inext + 1) >= 56)
            index1 = 1;
          int index2;
          if ((index2 = inextp + 1) >= 56)
            index2 = 1;
          int num = this.SeedArray[index1] - this.SeedArray[index2];
          if (num == int.MaxValue)
            --num;
          if (num < 0)
            num += int.MaxValue;
          this.SeedArray[index1] = num;
          this.inext = index1;
          this.inextp = index2;
          return num;
        }
    

    如果您同时通过2个线程访问该方法,则存在可能导致inext递增并且inextp不会递增(通常两者都得+)的危险,如果这种情况发生21次(inext之间的初始差异)和inextp是21)然后这一行:

    int num = this.SeedArray[index1] - this.SeedArray[index2];
    

    将开始使种子数组填充为0,并且在短暂的一段时间后,随机对象将完全断开,并一直返回0。

    危害预防: intext = 0; inextp = 21 线程1(t1)和线程2(t2)访问随机对象。 T1即将完成并位于

    this.inext = index1; //now this.inext = 1 and still this.inextp = 21 
    

    t2现在开始工作并且

        int inext = this.inext; //1
        int inextp = this.inextp; //21!
    

    t1以

    结束
    this.inextp = index2; //22
    

    一段时间后t2完成它的工作并保存递增的本地index1和index2

            this.inext = index1; //2
            this.inextp = index2; //22!
    

    如上所述,this.inext和this.inextp之间的初始差异为21 - 现在它只有20,再做20次并且随机将开始一直返回0

    1. solution1:当有可能被多个线程使用时,总是锁定随机。 解决方案2:这可能是一个有趣的技巧,复制反汇编的随机并使用InternalSample()方法使用的内部锁定对象编写自己的(是的,这会导致Random工作得慢得多但是如果你想为多个线程使用相同的对象任何可以避免每次外部锁定问题的原因。
    2. PS我很确定多线程访问我的随机是非常罕见的,但它不是,我发现代码中的一个错误导致一些客户经常访问它。由于该随机错误,我可以发现它并显着降低负载。至少那是一个小小的奖励。