using System; using System.Threading; namespace Recetas.Multithreading.Cap04.R0109 { // Representa una cuanta Bancaria: public class Cuenta { // Instancia Object para el bloque concurrente // a un sección crítica: private Object bloqueo = new Object(); private int saldo; // Objeto Random para simular la cantidad de dinero // a retirar: Random aleatorio = new Random(); public Cuenta(int saldoInicial) { saldo = saldoInicial; } // Retiro de dinero: public int Retirar(int cantidad) { // Comprueba que la cuenta tenga fondos para el retiro: if (saldo < 0) { throw new Exception ("Saldo Negativo."); } // Sección crítica. Sólo se permite una transacción // de retiro de forma simultánea: lock (bloqueo) { if (saldo >= cantidad) { Console.WriteLine ("Saldo antes del retiro: {0}", saldo.ToString()); Console.WriteLine ("Cantidad a retirar: -{0}", cantidad.ToString()); saldo -= cantidad; Console.WriteLine ("Saldo después del retiro: {0}", saldo.ToString()); return cantidad; } else { return 0; } } } // Simula la ejecución de 100 transacciones: public void RealizarTransaccion() { for (int i = 1; i <= 100; ++i) { // Realiza retiros entre 1 y 100 unidades monetarias: Retirar(aleatorio.Next(1, 101)); } } } public sealed class Banco { public static void Main() { Console.Title = "Uso de lock para transacciones bancarias"; Console.WriteLine (); // Crea un arreglo de 10 threads: Thread[] threads = new Thread[10]; // Una cuenta para arealizar transacciones, // y un saldo inicial de 1000 unidades monetarias: Cuenta c = new Cuenta(1000); // Crea las 10 instancias de Thread: for (int i = 0; i < 10; ++i) { Thread t = new Thread(new ThreadStart(c.RealizarTransaccion)); threads[i] = t; } // Inicia los threads para ejecución simultánea: for (int i = 0; i < 10; ++i) { threads[i].Start(); } Console.WriteLine (); } } }