47 votes

Est Fil.Sleep(1) spécial?

Joe Duffy (auteur de la Programmation Simultanée sur Windows) écrit dans cet article du blog de ce Thread.Sleep(1) est préféré au Fil.Sleep(0) parce qu'il va suspendre pour des personnes de même inférieur threads de priorité, non seulement l'égalité des threads de priorité que pour le Thread.Sleep(0).

L' .NET version de MSDN dit ce Thread.Sleep(0) est spécial, il va suspendre ce fil et permettre à d'autres threads en attente d'exécution. Mais il ne dit rien sur le Fil.Sleep(1) (pour tout .Version NET).

Alors, est-Fil.Sleep(1) en train de faire quelque chose de spécial?

Arrière-plan:

Je suis rafraîchir mes connaissances de la programmation simultanée. J'ai écrit un code C# afin de montrer visuellement que pré/post-incrémente et décrémente sont non-atomique et donc pas thread-safe.

Pour éviter d'avoir à créer des centaines de fils que je place à un Fil.Sleep(0) après l'incrémentation d'une variable partagée à la force de l'ordonnanceur pour exécuter un autre thread. Cette permutation de threads fait de la non-atomiques de la nature de pré/post-incrémentation/décrémentation de plus en plus évidents.

Fil de discussion.Sleep(0) semble provoque pas de retard supplémentaire, comme prévu. Cependant si je change de ce Thread.Sleep(1), il semble revenir à la normale du comportement en sommeil (par exemple. Je reçois à peu près un minimum de 1 ms de retard).

Cela signifie que tandis que le Thread.Sleep(1) peut être préféré, tout code qui l'utilise dans une boucle irait beaucoup plus lent.

Ce DONC, la question "quelqu'un Pourrait-il expliquer ce comportement intéressant avec Sleep(1)?" il est en quelque sorte pertinent, mais c'est le C++, concentré et ne fait que répéter les conseils de Joe Duffy article de blog.

Voici mon code pour toute personne intéressée (copié à partir de LinqPad, de sorte que vous pouvez avoir besoin d'ajouter une classe autour d'elle):

int x = 0;

void Main()
{
    List<Thread> threadList=new List<Thread>();
    Stopwatch sw=new Stopwatch();

    for(int i=0; i<20; i++)
    {
        threadList.Add(new Thread(Go)); 
        threadList[i].Priority=ThreadPriority.Lowest;
    }

    sw.Start();

    foreach (Thread thread in threadList)
    {
        thread.Start();
    } 


    foreach (Thread thread in threadList)
    {
        thread.Join();
    } 

    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds);

    Thread.Sleep(200);
    Console.WriteLine(x);
}

void Go()
{
    for(int i=0;i<10000;i++)
    {
        x++;
        Thread.Sleep(0);
    }
}

59voto

Matthew Watson Points 30804

Vous n'avez plus besoin d'utiliser Sleep(1) au lieu de Sleep(0) parce que Microsoft a modifié la mise en œuvre de l'API Windows Sleep().

À partir de la documentation MSDN pour Dormir(), c'est ce qui se passe maintenant avec le Sommeil(0):

Une valeur de zéro, le fil à abandonner le reste de sa tranche de temps pour n'importe quel autre thread qui est prêt à s'exécuter. Si il n'y a pas d'autres threads prêt à fonctionner, la fonction retourne immédiatement, et le fil continue l'exécution.

C'est ce qui se passait dans Windows XP:

Une valeur de zéro, le fil à abandonner le reste de sa tranche de temps de toute autre thread de priorité égale qui est prêt à s'exécuter. Si il n'y a pas d'autres threads de même priorité prêt à fonctionner, la fonction retourne immédiatement, et le fil continue l'exécution. Ce comportement a changé à partir de Windows Server 2003.

Notez la différence entre le "tout autre thread" et "toute autre thread de priorité égale".

La seule raison que Joe Duffy suggère d'utiliser Sleep(1) plutôt que de Dormir(0) c'est parce que c'est le plus court Sleep() valeur à prévenir la Sleep() de revenir immédiatement si il n'y a pas d'autres threads de même priorité prêt à être exécuté, lors de l'exécution sur Windows XP.

Vous n'avez pas besoin de vous inquiéter à ce sujet pour les versions de système d'exploitation après l'installation de Windows Server 2003 en raison du changement de comportement de Sleep().

J'attire votre attention sur cette partie de Joe blog:

Et même si il y a un explicite Sommeil, il y, la délivrance, il ne permet pas au producteur d'être prévu, parce que c'est à une priorité plus faible.

Dans XP, baisse des threads de priorité serait morte de faim, même si le thread principal (d'une priorité plus élevée) ont fait Dormir(0). Post-XP, cela n'arrivera plus car le Sommeil(0) permettra à la priorité la plus basse threads de s'exécuter.

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