dandan78
dandan78

Reputation: 13864

Random.Next() sometimes returns same number in separate threads

I have the following class

class Program
{
   static Random _Random = new Random();

   static void Main(string[] args)
   {
      ...
      for (int i = 0; i < no_threads; ++i)
      {
         var thread = new Thread(new ThreadStart(Send));
         thread.Start();
      }
      ...   
   }

   static void Send()
   {
      ...
      int device_id = _Random.Next(999999);
      ...
   }
}

The code creates the specified number of threads, starts each one, and assigns each thread a random device_id. For some reason, the first two threads that are created often have the same device_id. I can't figure out why this happens.

Upvotes: 10

Views: 4733

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1500635

Note: The most appropriate approach as of .NET 6 would be to use Random.Shared which is thread-safe.


Random is not thread-safe - you shouldn't be using the same instance from multiple threads. It can get much worse than just returning the same data - by using it from multiple threads, you can get it "stuck" in a state where it will always return 0, IIRC.

Obviously you don't just want to create a new instance for each thread at roughly the same time, as they'll end up with the same seeds...

I have an article which goes into the details of this and provides an implementation which lazily instantiates one instance of Random per thread using an incrementing seed.

Upvotes: 30

Grhm
Grhm

Reputation: 6834

Your example code only shows one use of _Random per thread. Assuming this is the case, you could also generate the random number in the main for loop and pass the random number into each thread as a parameter.

 for (int i = 0; i < no_threads; ++i)
 {
      var thread = new Thread(new ThreadStart(Send));
      thread.Start(_Random.Next(999999));
 }

and then modify your thread function to accept the parameter:

 static void Send(int device_id)
 {
    ...
    //int device_id = _Random.Next(999999);
    ...
 }   

Upvotes: 2

Darin Dimitrov
Darin Dimitrov

Reputation: 1038830

Random is a pseudo-random number generator and there's nothing preventing it from returning same result for multiple calls. After all there's a probability for this happening. Not to mention that according to the documentation:

Any instance members are not guaranteed to be thread safe.

So you shouldn't be calling the Next method at all from multiple threads.

Upvotes: 5

Related Questions