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