93 votes

Le thread C # Random Number Generator est-il sécurisé?

Quelqu'un peut-il me dire si la méthode C # Random.Next () est thread-safe?

95voto

Non, l'utilisation de la même instance à partir de plusieurs threads peuvent provoquer la rupture et le retour de tous les 0. Cependant, la création d'une version thread-safe (sans avoir besoin de méchant verrous sur chaque appel d' Next()) est simple. Adapté à partir de l'idée dans cet article:

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

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

L'idée est de garder un static Random variable pour chaque thread. Le moyen évident échoue, cependant, en raison d'un autre problème avec l' Random - si plusieurs instances sont créées à peu près au même moment (dans les 15ms), ils seront tous de retour les mêmes valeurs! Pour résoudre ce problème, nous créons un monde statique Random exemple pour générer les graines utilisées par chaque thread.

L'article ci-dessus, par la manière, le code de preuve à la fois de ces questions avec Random.

35voto

Mehrdad Afshari Points 204872

Il n'y a rien de spécial, en Next méthode pour parvenir à la sécurité des threads. Cependant, c'est une méthode d'instance. Si vous ne partagez pas les instances de l' Random entre différents threads, vous n'avez pas beaucoup à s'inquiéter.

Jon a de beaux messages sur ce sujet:

StaticRandom
Revisiter l'aléatoire

25voto

JSWork Points 464

La réponse officielle de Microsoft est une très forte pas:

http://msdn.microsoft.com/en-us/library/system.random.aspx#8
Il y a un très vilain effet secondaire qui peut se produire lorsque le même objet Aléatoire est utilisé par plusieurs threads: il s'arrête juste au travail

(c'est une condition de concurrence qui, lorsqu'il est déclenché, la valeur de retour de l '" aléatoire.Prochaine....' des méthodes de 0 (pour tous les appels ultérieurs))

14voto

Guffa Points 308133

Non, ce n'est pas thread-safe. Si vous devez utiliser la même instance à partir de différents threads, vous devez synchroniser l'utilisation.

Je ne vois pas vraiment pourquoi vous auriez besoin de cela, cependant. Il serait plus efficace que chaque thread ait sa propre instance de la classe Random.

9voto

rjroy Points 51

Une autre façon de traiter les threads consiste à utiliser ThreadLocal<T> comme suit:

 new ThreadLocal<Random>(() => new Random(GenerateSeed()));
 

La méthode GenerateSeed() devra renvoyer une valeur unique à chaque appel afin de garantir que les séquences de nombres aléatoires sont uniques dans chaque thread.

 static int SeedCount = 0;
static int GenerateSeed() { 
    return (int) ((DateTime.Now.Ticks << 4) + 
                   (Interlocked.Increment(ref SeedCount))); 
}
 

Travaillera pour un petit nombre de threads.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X