0

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

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

4 回答 4

2

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

不能说它比Random 构造函数的MSDN 文档更好

“默认种子值源自系统时钟并且具有有限的分辨率。因此,通过调用默认构造函数连续创建的不同 Random 对象将具有相同的默认种子值,因此将产生相同的集合随机数。这个问题可以通过使用单个 Random 对象来生成所有随机数来避免。您也可以通过修改系统时钟返回的种子值,然后将这个新的种子值显式提供给 Random(Int32 ) 构造函数。有关更多信息,请参阅 Random(Int32) 构造函数。

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

于 2012-06-01T06:53:35.727 回答
1

Random因为您在每次调用中实例化一个 newGenerateRandomCode并且调用花费的时间非常短,所以所有 3 个Random对象最终都具有相同的基于时间的种子,这意味着它们都将返回相同的第一个值。为您的对象创建一个字段,Random在程序开始时仅将其实例化一次,然后GenerateRandomCode使用该实例Random代替 - 您现在在调用random.NextDouble().

于 2012-06-01T06:52:51.780 回答
1

new Random()电话拉到外面GenerateRandomCode

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

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

我相信这将解决问题。

于 2012-06-01T06:52:54.317 回答
0

原因:没有给定任何种子值的随机数实例将DateTime.Now.Ticks值作为种子值。由于您的实例正在快速连续地重新创建,因此该实例会以相同的滴答声播种。因此相同的随机数。

证明:在代码中放置一些断点。然后你会得到真正的随机值,因为当它触发调试器时,在你按下 F10 或 F11 或 F5 之前会浪费时间。造成时间流逝。

解决方案:创建一个 Random 类的静态实例,并在任何你想要的地方使用它的 Next 函数。

于 2012-06-01T07:00:58.777 回答