Código
#include <stdio.h> #include <pthread.h> pthread_mutex_t MyMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t seguir2 = PTHREAD_COND_INITIALIZER; pthread_cond_t seguir = PTHREAD_COND_INITIALIZER; #define N 5 int aloja = 0; int sigo = 0; /* Cuando un thread -que debe tener el mutex ya tomado- llama a wait(), suelta el mutex y entra en espera bloqueante. DEBE TENER EL MUTEX YA TOMADO! Cuando un thread llama a signal(), otro thread en espera, de haberlo, se despierta de su wait() CON EL MUTEX YA ADQUIRIDO CON EL MUTEX YA ADQUIRIDO! */ void *freno (void *a) { for (;;){ // Tomo el mutex. pthread_mutex_lock(&MyMutex); // Hey!, quiero entrar, terminá lo que estás haciendo, te espero. aloja = 1; // Espero hasta que se "apague" la función avanzar. // Cuando se apaga, AUTOMATICAMENTE TOMO YO EL MUTEX!! // Si llegué hasta acá es porque yo tengo el mutex nadie mas lo puede tomar. // Terminé de hacer todo lo que quería hacer. aloja = 0; // Por más que lo ponga el 0, "avanzar" no puede entrar todavía, porque // yo tengo el mutex! /* Libero el mutex, es decir, ahora la función avanzar sí puede tomar el mutex, PERO a la vez no ya que está dentro de un wait esperando un SIGNAL no que libere un mutex. Aunque no está demás recordar que solo 1 puede tomar el mutex a la vez. */ pthread_mutex_unlock(&MyMutex); /* Cuando un thread llama a signal(), otro thread en espera, de haberlo, se despierta de su wait CON EL MUTEX YA TOMADO! pthread_cond_signal(&seguir2); */ /* Cuando un thread llama a broadcast(), todos los threads en espera, de haberlo, se despiertan de su wait CON EL MUTEX YA TOMADO, es decir en este caso, se pelean por quien toma el mutex. */ pthread_cond_broadcast(&seguir2); } } void *avanzar (void *b) { for (;;){ // Tomo yo el mutex, nadie más lo puede tomar. pthread_mutex_lock(&MyMutex); sigo++; // Libero, ahora si puede tomar el mutex la función "freno". pthread_mutex_unlock(&MyMutex); //sleep(3); // No puedo tomar el mutex hasta que la función freno recién llegue a la linea donde entra en espera! pthread_mutex_lock(&MyMutex); sigo--; // Libero el mutex, recien ahora pueden ejecutarse más funciones "freno", antes no porque yo tenía el // mutex tomado. pthread_mutex_unlock(&MyMutex); /* Esta señal está esperando "freno" para poder continuar, pero además de esperar la señal espera también que la cantidad de "sigo" sea igual a 0 */ /* Si sigo es un número mayor a 0, entonces de todos modos va a seguir esperando. */ pthread_cond_signal(&seguir); /*PERO! a la vez yo me bloqueo. Esperando ahora que "freno" me desbloque. */ /* Y a su vez freno está esperando que yo lo desbloquee. */ while (aloja != 0)pthread_cond_wait(&seguir2,&MyMutex); /* ¿Qué pasaría si avanzar toma el mutex e incrementa en 1 la variable "sigo" y al toque "freno" pone en 1 la variable aloja? Lo que pasaría es que la variable sigo se incrementa luego suelta el mutex, lo toma la función"freno" pone en 1 aloja pero como sigo es mayor que cero entonces SUELTA el mutex automáticamente y deja que siga funcionando "avanzar", entonces pueden pasar cosas!: Primero de todo, no se pueden ejecutar dos "frenos" a a la vez pero si se pueden ejecutar "avanzar" muchas veces. Entonces, avanzar toma el mutex y decrementa en 1 la variable sigo y al momento lo suelta, PERO "freno" todavía no puede hacer nada porque está esperando un signal, no está esperando que suelte el mutex (explicado anteriormente) Entonces yo le doy el signal y suponiendo que el numero de sigo es igual a 0, se ejecuta freno y yo entro en espera hasta que freno termine. */ } } int main (void) { int i; pthread_t prueba1[N],prueba2[N]; for (i=0; i<N; i++){ pthread_create(&prueba1[i],0,freno,"aloja"); pthread_create(&prueba2[i],0,avanzar,"chau"); } pthread_join(prueba1[0],0); return 0; }
El programa sigue está logica aunque las funciones no se llamen lector y escritor.
1. No puede haber un lector accediendo al arreglo al mismo tiempo que un escritor.
2. Varios lectores pueden acceder al arreglo simult´aneamente.
3. S´olo puede haber un escritor a la vez.
Y además cuando los lectores que están leyendo terminen su lectura pero no se puedan empezar nuevas lecturas hasta que el escritor escriba.
freno = escritor.
avanzar = lector.
Aunque en este caso no escriben ni leen nada solo muestran texto.
El problema es que no funciona y no sé que es lo que estoy pensando mal, el programa se congela es decir en algún momento queda esperando algo que nunca llega.