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 (); } } }
Standard input is empty
Saldo antes del retiro: 1000 Cantidad a retirar: -61 Saldo después del retiro: 939 Saldo antes del retiro: 939 Cantidad a retirar: -2 Saldo después del retiro: 937 Saldo antes del retiro: 937 Cantidad a retirar: -38 Saldo después del retiro: 899 Saldo antes del retiro: 899 Cantidad a retirar: -79 Saldo después del retiro: 820 Saldo antes del retiro: 820 Cantidad a retirar: -43 Saldo después del retiro: 777 Saldo antes del retiro: 777 Cantidad a retirar: -65 Saldo después del retiro: 712 Saldo antes del retiro: 712 Cantidad a retirar: -18 Saldo después del retiro: 694 Saldo antes del retiro: 694 Cantidad a retirar: -85 Saldo después del retiro: 609 Saldo antes del retiro: 609 Cantidad a retirar: -47 Saldo después del retiro: 562 Saldo antes del retiro: 562 Cantidad a retirar: -85 Saldo después del retiro: 477 Saldo antes del retiro: 477 Cantidad a retirar: -39 Saldo después del retiro: 438 Saldo antes del retiro: 438 Cantidad a retirar: -77 Saldo después del retiro: 361 Saldo antes del retiro: 361 Cantidad a retirar: -28 Saldo después del retiro: 333 Saldo antes del retiro: 333 Cantidad a retirar: -11 Saldo después del retiro: 322 Saldo antes del retiro: 322 Cantidad a retirar: -24 Saldo después del retiro: 298 Saldo antes del retiro: 298 Cantidad a retirar: -15 Saldo después del retiro: 283 Saldo antes del retiro: 283 Cantidad a retirar: -96 Saldo después del retiro: 187 Saldo antes del retiro: 187 Cantidad a retirar: -35 Saldo después del retiro: 152 Saldo antes del retiro: 152 Cantidad a retirar: -97 Saldo después del retiro: 55 Saldo antes del retiro: 55 Cantidad a retirar: -5 Saldo después del retiro: 50 Saldo antes del retiro: 50 Cantidad a retirar: -20 Saldo después del retiro: 30 Saldo antes del retiro: 30 Cantidad a retirar: -10 Saldo después del retiro: 20 Saldo antes del retiro: 20 Cantidad a retirar: -6 Saldo después del retiro: 14 Saldo antes del retiro: 14 Cantidad a retirar: -9 Saldo después del retiro: 5 Saldo antes del retiro: 5 Cantidad a retirar: -2 Saldo después del retiro: 3 Saldo antes del retiro: 3 Cantidad a retirar: -1 Saldo después del retiro: 2 Saldo antes del retiro: 2 Cantidad a retirar: -2 Saldo después del retiro: 0