1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.thread class CuentaBancaria(var saldo: Int) { private val lock = ReentrantLock() fun depositar(cantidad: Int) { lock.lock() try { saldo += cantidad println("Depósito de $cantidad. Saldo actual: $saldo") } finally { lock.unlock() } } fun retirar(cantidad: Int) { lock.lock() try { if (saldo >= cantidad) { saldo -= cantidad println("Retiro de $cantidad. Saldo actual: $saldo") } else { println("Saldo insuficiente para el retiro de $cantidad") } } finally { lock.unlock() } } } fun main() { val cuenta = CuentaBancaria(1000) val hilo1 = thread { for (i in 1..5) { cuenta.depositar(100) Thread.sleep(100) } } val hilo2 = thread { for (i in 1..3) { cuenta.retirar(200) Thread.sleep(150) } } val hilo3 = thread { for (i in 1..4) { cuenta.depositar(50) Thread.sleep(200) } } val hilo4 = thread { for (i in 1..2) { cuenta.retirar(300) Thread.sleep(100) } } hilo1.join() hilo2.join() hilo3.join() hilo4.join() println("Saldo final: ${cuenta.saldo}") } |
Este código en Kotlin implementa un programa de simulación de gestión de transacciones bancarias concurrentes utilizando hilos y bloqueos (locks) en un contexto de una cuenta bancaria. Aquí está la explicación detallada del código:
- Se define una clase llamada
CuentaBancaria
que representa una cuenta bancaria con un saldo inicial. Esta clase tiene dos métodos principales:depositar(cantidad: Int)
: Este método permite depositar una cantidad específica en la cuenta. Utiliza un bloqueo (lock) medianteReentrantLock
para garantizar que las operaciones de depósito sean seguras en entornos concurrentes. Después de depositar, muestra un mensaje que indica la cantidad depositada y el saldo actual.retirar(cantidad: Int)
: Este método permite retirar una cantidad específica de la cuenta. También utiliza un bloqueo para garantizar que las operaciones de retiro sean seguras. Verifica si hay suficiente saldo antes de retirar y muestra mensajes apropiados en función del resultado.
- En la función
main
, se crea una instancia deCuentaBancaria
llamadacuenta
con un saldo inicial de 1000. - Se crean cuatro hilos (
hilo1
,hilo2
,hilo3
, yhilo4
) que ejecutan diferentes secuencias de operaciones en la cuenta:hilo1
: Realiza 5 depósitos de $100 cada uno, con un intervalo de 100 ms entre cada depósito.hilo2
: Realiza 3 retiros de $200 cada uno, con un intervalo de 150 ms entre cada retiro.hilo3
: Realiza 4 depósitos de $50 cada uno, con un intervalo de 200 ms entre cada depósito.hilo4
: Realiza 2 retiros de $300 cada uno, con un intervalo de 100 ms entre cada retiro.
- Se utiliza
join()
en cada hilo para asegurarse de que todos los hilos completen sus operaciones antes de imprimir el saldo final. - Finalmente, se imprime el saldo final de la cuenta después de que todos los hilos hayan completado sus transacciones.
Este código ilustra cómo se pueden utilizar bloqueos (locks) para gestionar transacciones bancarias concurrentes de manera segura, evitando condiciones de carrera y garantizando la consistencia de los datos en una aplicación multi-hilo.
Las llamadas lock.lock()
y lock.unlock()
se utilizan para crear secciones críticas del código en las funciones depositar
y retirar
. Aquí está cómo funcionan:
lock.lock()
: Cuando un hilo llama alock.lock()
, adquiere un bloqueo en el objetolock
, lo que significa que ningún otro hilo puede entrar en una sección crítica protegida por el mismo bloqueo hasta que se libere el bloqueo. En este caso, se usa para asegurar que solo un hilo a la vez puede ejecutar las secciones críticas dentro de las funcionesdepositar
yretirar
.lock.unlock()
: Después de que un hilo ha terminado de ejecutar las operaciones críticas dentro de una sección protegida por el bloqueo, debe llamar alock.unlock()
para liberar el bloqueo. Esto permite que otros hilos adquieran el bloqueo y ejecuten las secciones críticas de manera concurrente.
El objetivo de utilizar bloqueos es garantizar que las operaciones de depósito y retiro se realicen de manera segura y eviten condiciones de carrera, donde varios hilos intentan acceder y modificar el saldo al mismo tiempo. Los bloqueos permiten que solo un hilo acceda a la sección crítica a la vez, asegurando la coherencia de los datos.