#include #include #include #include // Para sleep() // 1. Estructura que simula el Monitor typedef struct { int saldo; pthread_mutex_t puerta_cabina; // Garantiza la exclusión mutua pthread_cond_t condicion_saldo; // Variable de condición para hacer esperar a los hilos } MonitorCuenta; MonitorCuenta cajero; // Instancia global de nuestro monitor // Inicializar las variables del monitor void inicializar_monitor(MonitorCuenta *m) { m->saldo = 0; pthread_mutex_init(&m->puerta_cabina, NULL); pthread_cond_init(&m->condicion_saldo, NULL); } // 2. Procedimiento del Monitor: Retirar dinero void retirar(MonitorCuenta *m, int cantidad, int id) { // Al entrar al procedimiento, el hilo cierra la puerta (LOCK) pthread_mutex_lock(&m->puerta_cabina); printf("Hilo %d quiere retirar $%d...\n", id, cantidad); // Si no hay saldo suficiente, el hilo se "duerme" y la puerta se ABRE automáticamente while (m->saldo < cantidad) { printf("Hilo %d en ESPERA (saldo insuficiente).\n", id); // Esta función bloquea el hilo y libera el mutex al mismo tiempo pthread_cond_wait(&m->condicion_saldo, &m->puerta_cabina); } // Si despertó y salió del bucle, es porque ya hay saldo y volvió a cerrar la puerta m->saldo -= cantidad; printf("Hilo %d retiro $%d con exito. Saldo actual: $%d\n", id, cantidad, m->saldo); // Al salir del procedimiento, abre la puerta para los demás (UNLOCK) pthread_mutex_unlock(&m->puerta_cabina); } // 3. Procedimiento del Monitor: Depositar dinero void depositar(MonitorCuenta *m, int cantidad, int id) { // Al entrar, cierra la puerta pthread_mutex_lock(&m->puerta_cabina); m->saldo += cantidad; printf("Hilo %d deposito $%d. Saldo actual: $%d\n", id, cantidad, m->saldo); // Notifica (despierta) a todos los hilos que estén esperando por saldo pthread_cond_broadcast(&m->condicion_saldo); // Abre la puerta pthread_mutex_unlock(&m->puerta_cabina); } // --- HILOS (Procesos) --- void* proceso_retirar(void* arg) { int id = *((int*)arg); retirar(&cajero, 100, id); // Intenta retirar $100 return NULL; } void* proceso_depositar(void* arg) { int id = *((int*)arg); depositar(&cajero, 150, id); // Deposita $150 return NULL; } int main() { pthread_t h1, h2; int id1 = 1, id2 = 2; printf("==========================================\n"); printf(" Iniciando simulador de Monitor de Cuenta \n"); printf("==========================================\n\n"); inicializar_monitor(&cajero); // El Hilo 1 llega primero e intenta retirar dinero, pero la cuenta está en $0 pthread_create(&h1, NULL, proceso_retirar, &id1); sleep(2); // Pausa de 2 segundos para asegurar que el Hilo 1 se quede bloqueado esperando // El Hilo 2 llega más tarde y deposita el dinero pthread_create(&h2, NULL, proceso_depositar, &id2); // Esperar a que terminen pthread_join(h1, NULL); pthread_join(h2, NULL); // Destruir variables del monitor para liberar memoria pthread_mutex_destroy(&cajero.puerta_cabina); pthread_cond_destroy(&cajero.condicion_saldo); printf("\nTodas las transacciones finalizaron.\n"); return 0; }