3

I already searched for this question but none of the solutions I found helped. Maybe somebody can help me.

I have the following loop:

private static readonly Random RANDOM = new Random();
...
int[] array; // is initialized, when used. ;)
if (array.Sum() != 0)
{
    int j = 0;
    do {
        j = RANDOM.Next(8);
    } while (array[j] == 0);
}

This whole loop is in another loop which, again, is in a Parallel.Foreach-loop. It seems, that j is always 0. Most times it is not noticeable, but if array[0] == 0, then it won't get out of the loop. I got the suspicion that the do-while-loop might be to fast. But also after some seconds (~30) it does not leave the loop. So the Random does not seem to return a new or different value (even in the same thread).

I also tried this solution but with no effect.

Community
  • 1
  • 1
Dave J
  • 475
  • 9
  • 18

3 Answers3

4

Try this instead, since Random is not thread safe:

private static Random RANDOM = new Random();
private static object _randomLock = new object();

...

int[] array; // is initialized, when used. ;)
if (array.Sum() != 0)
{
    int j = 0;
    do {
        lock(_randomLock)
        {
            j = RANDOM.Next(8);
        }
    } while (array[j] == 0);
}
qJake
  • 16,821
  • 17
  • 83
  • 135
  • 2
    The _randomLock is superfluous: just lock on the static readonly RANDOM instance. – Haney May 31 '13 at 20:29
  • 2
    @DavidH This is true, but for educational purposes, it's good to start out with locking on an empty `object` so that the concept becomes clear, before moving on to explaining that you can, in fact, lock on any static object within scope, not just `object`. – qJake May 31 '13 at 20:30
  • 1
    I 100% agree, thus not downvoting. :) – Haney May 31 '13 at 20:31
  • as I said, I already tried this version and it didn't work in my code. even so i know the principle of `lock` – Dave J May 31 '13 at 20:37
  • 2
    There must be something you've omitted then, because as it stands, that code will produce random numbers even if it is accessed from multiple threads. Have you breakpointed/debugged to see if `j` is actually receiving a value from `RANDOM.Next(8)`? Perhaps try `?RANDOM.Next(8);` in the Immedate window while the program is paused? – qJake May 31 '13 at 20:43
  • tried the `?RANDOM.Next(8);`. it returned `0` (more than once). – Dave J May 31 '13 at 20:51
  • 1
    Wait, I missed this ... why is it marked `readonly`? That's probably why it isn't working, remove that and just make it static. – qJake May 31 '13 at 20:58
  • Unfortunately this makes no difference (i tried it). `readonly` is just not allowing a re-definition of the variable. and a re-definition should not be necessary here. – Dave J May 31 '13 at 21:17
3

Thanks for the quick answers. Matthew's answer already gave me what i needed.
I used

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(); 
    } 
}

for my solution. It works very well and quite fast.

Community
  • 1
  • 1
Dave J
  • 475
  • 9
  • 18
  • OP, This was the same question that I initially asked you about whether you were locking properly on your shared/static Random instance. You said that you were. That can't have been true because this code clearly does the same thing... – Haney Jun 06 '13 at 21:40
  • Does not seem so, because when I tried the other suggestion it didn't work. – Dave J Jun 06 '13 at 21:44
  • It's not worth arguing, but I am glad that ultimately you got a working solution! – Haney Jun 06 '13 at 21:49
2

Random is not threadsafe and isn't sufficiently random for parallel operations. Consider using a thread safe RNG such as RNGCryptoServiceProvider, but know that it will be a fair bit slower than Random as the algorithm to generate numbers is much more complex.

Haney
  • 32,775
  • 8
  • 59
  • 68