Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting random numbers in a thread-safe way

Here is a nice article describing thread safety of random numbers:Getting random numbers in a thread-safe way

But I'm stuck with the "RandomGen2" example:

public static class RandomGen2 
{ 
    private static Random _global = new Random(); 
    [ThreadStatic] 
    private static Random _local;

    public static int Next() 
    { 
       Random inst = _local; 
       if (inst == null) 
       { 
           int seed; 
           lock (_global) seed = _global.Next(); 
           _local = inst = new Random(seed); 
       } 
       return inst.Next(); 
   } 

}

Why is the thread static field copied to local variable: Random inst = _local; ? Why not to simply use

if (_local == null) .... return _local.Next()

like image 626
Alexey Bychkov Avatar asked Aug 22 '14 13:08

Alexey Bychkov


1 Answers

Note: since writing this answer, I've become aware of issues creating multiple Random instances, even though it sounds like it should work. I've generally found that a better alternative is to have a single Random instance and just lock on that. Although that is a single potential bottleneck, in most applications it won't cause problems.


I suspect it's just to avoid the cost of reading the thread-static variable multiple times. It's relatively inefficient to do so, compared with reading a local variable.

Your suggestion would work, but it would be slightly less efficient, that's all. In other cases, there would be the possibility of the value changing between fetches - but of course that's not a problem in this case, as it's a thread-local variable.

With .NET 4 and higher, this would be simpler using ThreadLocal<T>:

public static class RandomGen2 
{ 
    private static Random _global = new Random(); 
    private static ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
    {
        int seed;
        lock (_global) seed = _global.Next();
        return new Random(seed);
    });


    public static int Next() 
    { 
        return _local.Value.Next();
    } 
}
like image 65
Jon Skeet Avatar answered Sep 30 '22 09:09

Jon Skeet