views:

261

answers:

9

I'm not asking if these are truly random. I just wanted to know if two users hit the a page at the same time can they get the same random number? I'm thinking if i run this on a multicore server will i generate the same randon number a good amount of time due to syncing or whatever other reasons?

public static class SBackend
{
    static Random randObj = null;
    public static void init()
    {
        randObj = new Random((int)DateTime.Now.ToBinary());
        runFirstTime();
    }

    public static long getRandomId()
    {
        long randNum = (long)randObj.Next() << 33;
        randNum |= (uint)randObj.Next() << 2;
        randNum |= (uint)randObj.Next() & 3;
        return randNum;
    }
}
+3  A: 

well, if you only use it to generate random numbers which are never same, why not use System.Guid.NewGuid()?

rezna
"never same" - well, Guid is **unlikely** to be the same; but it is not guaranteed.
Marc Gravell
Well, You can't get better than unlikely with a RNG anyway.
Joey
A: 

Pseudo-random number generators (PRNGs) are only as good as the seed values that they have. Now I see that you've defined these as static classes and static methods, so assuming that you have put proper safety in place to ensure that getRandomId() is not being called by multiple threads simultaneously, then you should be in OK shape.

However, locking the access to getRandomId will introduce a bottleneck, and won't scale infinitely as your traffic increases.

scwagner
+7  A: 

Yes it is possible for that to generate the same numbers. The seed adds nothing (it is time based by default anyway).

Also - if it is static, you should synchronize it (Next is not thread-safe):

static readonly Random rand = new Random();
public static int NextInt32() {
    lock(rand) { return rand.Next();}
}
public static long NextInt64() {
    lock(rand) { // using your algorithm...
        long randNum = (long)rand.Next() << 33;
        randNum |= (uint)rand.Next() << 2;
        randNum |= (uint)rand.Next() & 3;
        return randNum;
    }
}

This can still generate the same number by coincidence of course...

Perhaps consider a cryptographic random number generator if entropy is important.

Marc Gravell
Even with a CSPRNG you can get the same number :)
Joey
@Johannes - indeed, there is only a finite number of numbers to go around...
Marc Gravell
+1  A: 

You could use the lock mechanism that ensures that only one thread at the time can access the Random object.

 public static class ThreadSafeRandom
{
    private static Random r = new Random();
    public static double NextDouble()
    {
        lock (r)
        {
            return r.NextDouble();
        }
    }

    public static int Next(int min, int max)
    {
        lock (r)
        {
            return r.Next(min, max);
        }
    }
}
Alex Pacurar
A: 

The odds would be so low you might never see it, but there is always a chance, not matter how impossible the odds... Have you though of usind GUID to decrease the chances of duplication, or is that not an option?

Link on wiki below might give you some more useful info.

Random Numbers

kevchadders
A: 

It's always going to be a possibility that you generate the same number when you use the basic Random class. I better approach would be to use System.Security.Cryptography.RandomNumberGenerator which will create cryptographically strong random values.

Iain Hoult
+1  A: 

You can use a linear congruential generator in a synchronized function to generate pseudo-random numbers that only repeat themselves every m requests (see the article for how to write one). Make m a 64-bit value, and it becomes highly unlikely that you'll ever get enough requests to repeat yourself, let alone serve the same number to two concurrent visitors.

Michiel Buddingh'
Additionally, in a threaded environment, you can make one generator for each of the N workers, and step them by N step each time, so worker 1 uses X1, xN+1, x2N+1, ..., worker 2 uses x2, xN+2, x2N+2.... and there are no collisions and no requirement for synchronization between workers.
Pete Kirkham
A: 

As others have said, yes you can have two random values be the same if the two threads ask for the random value within the same tick.

Here's another thread safe random implementation. This one uses less locks per request and is therefore faster.

public static class ThreadSafeRandom
{
    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();
    }
}

See "Getting random numbers in a thread-safe way" by the Parallels team for more info.

Cameron MacFarland
+1  A: 

If you want a session number, use a GUID.