with visual threadstart threads thread new net multi method example espaƱol book c# multithreading

visual - threadstart c#



Es Thread.Sleep(1) especial? (1)

Joe Duffy (autor de Programación concurrente en Windows ) escribe en este artículo de blog que Thread.Sleep (1) es preferible a Thread.Sleep (0) porque suspenderá para hilos de prioridad igual o inferior, no solo hilos de prioridad igual que para Thread. .Sueño (0).

La versión .NET de MSDN dice que Thread.Sleep (0) es especial, suspenderá este hilo y permitirá que se ejecuten otros hilos en espera. Pero no dice nada sobre Thread.Sleep (1) (para cualquier versión de .NET).

Entonces, ¿está Thread.Sleep (1) realmente haciendo algo especial?

Fondo:

Estoy refrescando mi conocimiento de la programación concurrente. Escribí un código C # para mostrar de forma visible que los incrementos y decrementos pre / post no son atómicos y, por lo tanto, no son seguros para subprocesos.

Para evitar la necesidad de crear cientos de subprocesos, coloco un Thread.Sleep (0) después de incrementar una variable compartida para forzar al planificador a ejecutar otro hilo. Este intercambio regular de hilos hace que la naturaleza no atómica del incremento / decremento pre / post sea más obvia.

Thread.Sleep (0) parece no causar ningún retraso adicional, como se esperaba. Sin embargo, si cambio esto a Thread.Sleep (1), parece volver al comportamiento de sueño normal (por ejemplo, recibo aproximadamente un mínimo de 1ms de retraso).

Esto significaría que, si bien es preferible Thread.Sleep (1), cualquier código que lo use en un bucle se ejecutará mucho más lento.

Esta pregunta SO: "¿Podría alguien explicar este comportamiento interesante con Sleep (1)?" es algo relevante, pero está enfocado en C ++ y simplemente repite la guía en el artículo de blog de Joe Duffy.

Aquí está mi código para cualquier persona interesada (copiado de LinqPad, por lo que puede necesitar agregar una clase al respecto):

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


Ya no es necesario utilizar Sleep(1) lugar de Sleep(0) porque Microsoft cambió la implementación de la API de Windows Sleep() .

Desde la documentación de MSDN para Sleep () , esto es lo que sucede ahora con Sleep (0):

Un valor de cero hace que el subproceso renuncie al resto de su división de tiempo a cualquier otro subproceso que esté listo para ejecutarse. Si no hay otros subprocesos listos para ejecutarse, la función regresa inmediatamente y el subproceso continúa la ejecución.

Esto es lo que solía ocurrir en Windows XP:

Un valor de cero hace que el subproceso renuncie al resto de su división de tiempo a cualquier otro subproceso de igual prioridad que esté listo para ejecutarse. Si no hay otros hilos de igual prioridad listos para ejecutarse, la función regresa inmediatamente y el hilo continúa la ejecución. Este comportamiento cambió a partir de Windows Server 2003.

Tenga en cuenta la diferencia entre "cualquier otro hilo" y "cualquier otro hilo de igual prioridad".

La única razón por la que Joe Duffy sugiere usar Sleep (1) en lugar de Sleep (0) es porque es el valor Sleep () más corto que evitará que Sleep () vuelva inmediatamente si no hay otros hilos de igual prioridad listos para ejecutarse. , cuando se ejecuta en Windows XP.

No necesita preocuparse por esto para las versiones del SO después de Windows Server 2003 debido al cambio en el comportamiento de Sleep ().

Llamo vuestra atención sobre esta parte del blog de Joe:

Y a pesar de que hay un sueño explícito allí, emitirlo no permite programar al productor porque tiene una prioridad más baja.

En XP, los subprocesos de menor prioridad se morirían de hambre incluso si el hilo principal (de mayor prioridad) lo hiciera Dormir (0). Después de XP, esto ya no ocurrirá porque Sleep (0) permitirá que se ejecuten los subprocesos de menor prioridad.