using System; using System.Threading; namespace Recetas.Multithreading.Cap02.R0201 { public sealed class Contadores { public static void Main() { Console.Title = "Demostración de Contadores Sincronizados y No Sincronizados"; Console.WriteLine (); Console.WriteLine ("--- Resultado Inconsiste de Contador ---"); // Creación de instancia de `ContadorBase`: ContadorEstandar contador = new ContadorEstandar(); // Creación de threads: Thread t1 = new Thread (() => ProbarContadores(contador)); Thread t2 = new Thread (() => ProbarContadores(contador)); Thread t3 = new Thread (() => ProbarContadores(contador)); // Inicio ejecución threads: t1.Start(); t2.Start(); t3.Start(); // Espera a que todos terminen: t1.Join(); t2.Join(); t3.Join(); Console.WriteLine ("\tCuenta total: {0}", contador.Contador.ToString()); Console.WriteLine ("\n--- Resultado Consiste de Contador ---"); // Creación de contador sincrónico: ContadorSincronizado contadorSinc = new ContadorSincronizado(); // Creación de nuevos threads: t1 = new Thread (() => ProbarContadores(contadorSinc)); t2 = new Thread (() => ProbarContadores(contadorSinc)); t3 = new Thread (() => ProbarContadores(contadorSinc)); // Inicio ejecución threads: t1.Start(); t2.Start(); t3.Start(); // Espera a que todos terminen: t1.Join(); t2.Join(); t3.Join(); Console.WriteLine ("\tCuenta total: {0}\n", contadorSinc.Contador.ToString()); Console.WriteLine ("Presione `Enter` para terminar."); } // Método que invoca 100 mil veces los métodos `Incrementar` // y `Decrementar`: private static void ProbarContadores (ContadorBase contador) { for (int i = 0; i < 100000; ++i) { contador.Incrementar(); contador.Decrementar(); } } } public abstract class ContadorBase { public abstract void Incrementar(); public abstract void Decrementar(); } // Esta clase no cuenta con un mecanismo de // sincronización de las operaciones de incremento // y decremento; los resultados pueden ser inconsistentes: public class ContadorEstandar : ContadorBase { private int contador; public int Contador { get { return contador; } } public override void Incrementar() { ++contador; } public override void Decrementar() { --contador; } } // Clase que sincroniza los incrementos y decrementos // de forma sincrónica usando la clase Interlocked: public class ContadorSincronizado : ContadorBase { private int contador; public int Contador { get { return contador; } } public override void Incrementar() { Interlocked.Increment (ref contador); } public override void Decrementar() { Interlocked.Decrement (ref contador); } } }