vendredi 29 avril 2022

C#: state of a static member variable `Random` inside an instantiable object class

Consider the following code example. I have a class Randomiser that has a static member variable public static Random rand. I can instantiate the Randomiser object as many times as I want, while I can access the member variable public static Random rand at any scope. At each time I call rand.Next(), I expect that the variable rand changes its status. In particular, I can call rand.Next() in multiple threads as in the example code.

Because the Random rand is a static variable, any call of rand.Next() method will refer to the same memory stack, and it is supposed to use the same random states. This does not have any issue if rand.Next() is called in a single process as they will be executed in a sequential order and the random state is not mixed up. However, when multiple threads are invoking the rand.Next() method, and if they happen to call it exactly at the same time, if this is somehow possible, it is unclear how the random state should change; rand.Next() is not only a read-access but it also changes the random state.

It appears to be a very theoretical and even weird question, but is there anyone who can imagine what is going to happen to the Random rand's random state when multiple threads are invoking at identical CPU clock?

    class Randomiser
    {
        public static Random rand = new 
                      Random(DateTime.UtcNow.GetHashCode());
                  
        public Randomiser(in string _name_) { this.name = _name_; }

        public string name = "";
        public int    num = -1;
    }
    class Program
    {   
        static void Main()
        {
            Randomiser[] Guys = 
            { 
                new Randomiser("Charlie"), 
                new Randomiser("Fox")
            };

            double for_ = 0.1;
            bool run = true;
            var t0 = DateTime.UtcNow;   
            
            new Thread(()=>
            { 
                while(run) 
                { 
                    Guys[0].num = Randomiser.rand.Next(); 
                    Console.WriteLine($"{Guys[0].name}: {Guys[0].num}");
                } 

            }).Start();

            new Thread(()=>
            { 
                while(run) 
                { 
                    Guys[1].num = Randomiser.rand.Next(); 
                    Console.WriteLine($"{Guys[1].name}: {Guys[1].num}");
                } 

            }).Start();
            
            while (true)
            {
                if ((DateTime.UtcNow - t0).TotalSeconds > for_)
                {
                    run = false;
                    break;
                }
            }
        }

        Console.ReadLine();
        return;
    }



Aucun commentaire:

Enregistrer un commentaire