Принятый ответ на этот вопрос , и подобное обсуждение сегодня на работе заставило меня задуматься о чем-то.
Вопрос был о том, как безопасно генерировать случайные числа в мультимногопоточная программа.Принятый ответ требует использования локального хранилища потоков, эффективно создавая один генератор случайных чисел на поток.Интересно, действительно ли это хорошая идея?
Допустим, у нас одновременно запущены два потока (вполне возможно в многоядерной системе), и оба вызывают конструктор Random
по умолчанию для создания иинициализировать генератор случайных чисел в локальном хранилище потока.Поскольку они не передали параметр seed, Random
использует системное время в качестве seed.Таким образом, оба генератора случайных чисел были инициализированы с одним и тем же начальным числом.Оба они будут генерировать одну и ту же последовательность случайных чисел.
Поскольку эти потоки выделяются из пула потоков, вы никак не можете связать конкретный объект с конкретным потоком.Или, в случае вышеупомянутого вопроса, вы не можете гарантировать, какой поток пула выполнит следующий запрос.Итак, представьте, что происходит следующее:
At startup, two requests come in simultaneously.
Two threads are created, each initializing a random number generator with the same seed.
Each thread generates three random numbers. They will be identical in both threads.
Next request comes in. It's assigned to thread #1.
It generates a random number and exits.
Some period of time elapses.
Next request comes in. It's assigned to thread #2.
It generates the same random number that thread #1 did just a while ago.
Это может продолжаться бесконечно, хотя я сомневаюсь, что это будет пинг-понг довольно сильно.Дело в том, что оба потока имеют одинаковый PRNG и вероятность повторения последовательности очень высока.Я понимаю, что P в PRNG означает «псевдо», но это немного много.
Я думаю, что несколько потоков могут инициализировать экземпляр Random
с тем же начальным значением.Если это произойдет, то "случайность" по крайней мере некоторых вещей в приложении пострадает.Последствия этого, конечно, зависят от приложения.
Что я не знаю, так это то, что если PRNG инициализируются с разными начальными значениями, делает ли последовательность, видимая клиентом, более случайной, менее случайной,или примерно так же?То есть, если бы я написал:
var rnd1 = new Random(123);
var rnd2 = new Random(654);
for (int i = 0; i < OneMillion; ++i)
{
numbers.Add(rnd1.Next());
numbers.Add(rnd2.Next());
}
Была бы последовательность чисел, которую я сгенерировал, более или менее случайной, чем если бы я просто генерировал два миллиона из любого из PRNG?