为什么这个随机字符串生成器总是返回相同的值

时间:2012-06-01 06:49:35

标签: c# random concurrency

我今天遇到一个奇怪的问题,我能理解其中的原因。采取以下控制台程序。

internal class Program
    {
        private static void Main(string[] args)
        {
            string s1 = GenerateRandomCode(8);
            string s2 = GenerateRandomCode(8);
            string s3 = GenerateRandomCode(8);
        }

        public static string GenerateRandomCode(int length)
        {
            string charPool = "ABCDEFGOPQRSTUVWXY1234567890ZabcdefghijklmHIJKLMNnopqrstuvwxyz";
            StringBuilder rs = new StringBuilder();
            Random random = new Random();

            for (int i = 0; i < length; i++)
            {
                rs.Append(charPool[(int)(random.NextDouble() * charPool.Length)]);
            }

            return rs.ToString();
        }
    }

如果我在程序的位置放置一个断点并运行程序,则s1,s2,s3的值都相等。现在,如果我在s2处放置一个断点,例如返回的值将是不同的。

看起来像某种并发问题?发生了什么事?

由于

4 个答案:

答案 0 :(得分:2)

随机数生成器实际上并非完全随机:给定相同的种子值,多个实例将生成相同的随机序列。

对于Random构造函数

,不能说比MSDN documentation更好
  

“默认种子值是从系统时钟派生而来的   有限分辨率。结果,不同的Random对象就是   通过调用默认构造函数将紧密连续创建   具有相同的默认种子值,因此将产生   相同的随机数集。使用可以避免此问题   单个Random对象生成所有随机数。你也可以   通过修改系统返回的种子值来解决它   时钟然后明确地提供这个新的种子值   随机(Int32)构造函数。有关更多信息,请参阅随机(Int32)   构造函数“。

因此,在您的情况下,您需要将Random实例保持为类级别字段或函数参数,并仅将其实例化一次。

答案 1 :(得分:1)

因为您在每次调用Random时都实例化了一个新GenerateRandomCode,并且由于调用所花费的时间非常少,所以所有3个Random个对象最终都使用相同的基于时间的种子,意味着他们都将返回相同的第一个值。为您的Random对象创建一个字段,在程序开始时只对其进行一次实例化,然后让GenerateRandomCode使用Random的实例 - 现在您将获得不同的值致电random.NextDouble()

答案 2 :(得分:1)

new Random()电话拉出GenerateRandomCode

由于您每次都在重新创建并快速连续调用它,因此它可能会获得相同的随机种子值。

您可以将其设置为静态,或使用依赖注入(传入)。

我相信这样可以解决问题。

答案 3 :(得分:0)

原因:未给定任何种子值的随机数实例将DateTime.Now.Ticks值作为种子值。由于您的实例正在以非常快的连续方式重新创建,因此实例将以相同的刻度进行播种。因此相同的随机数。

证明:在代码中添加一些断点。然后你会得到真正的随机值,因为它会打击一个调试器,在你按F10或F11或F5之前会有一段时间。造成时间流逝。

解决方案:创建一个Random类的静态实例,并根据需要使用其Next函数。