Estamos migrando de sistemas de foros, por favor repórtanos cualquier problema a [email protected], si te llega a tu bandeja de entrada o a spam un correo que te dice que se solicitó el cambio de contraseña, no te alarmes, es un procedimiento normal de la migración, cambia tu contraseña porque no hay compatibilidad en el sistema de cifrado del viejo sistema con el sistema nuevo, por eso debes resetear tu clave con ese enlace.

[C] Programación concurrente - Lectores y escritores.

GGZGGZ
editado 7 de mayo en Programación

El programa sigue está logica:

  1. No puede haber un lector accediendo al arreglo al mismo tiempo que un escritor.
  2. Varios lectores pueden acceder al arreglo simultáneamente.
  3. Sólo 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.

El problema que estoy teniendo es que se ejecutan demasiados escritores, o sea le doy una extrema prioridad a los escritores y no sé si está bien que pase eso realmente.

#include <stdio.h>
#include <pthread.h>

#define N 15
#define ARRLEN  1024

pthread_mutex_t MyMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t seguir = PTHREAD_COND_INITIALIZER;
pthread_cond_t seguir2 = PTHREAD_COND_INITIALIZER;

int arr[ARRLEN];

// Cantidad de funciones "lectores" que se están ejecutando.
int lectores = 0;
// Variable utilizada por si quiero escribir.
int wannawrite = 0;


void *escritor(void *arg)
{
  int i;
  int num = *((int *)arg);
  for (;;) {
    /* 
       Escribo el mutex al principio y este está tomando toda la función porque no pueden 
       haber más de 1 escritor a la vez.
    */
    pthread_mutex_lock(&MyMutex);

    /* Hey!!, quiero escribir!!, ahora todos deben dormir hasta que termine de escribir.*/
    wannawrite = 1;

    /* Espero hasta que todos los que estan leyendo, terminen de leer y se pogan a dormir
       De no ser así libero el mutex.

       wait(): Si tiene la señal, entonces despierta con EL MUTEX YA ADQUIRIDO. 
    */
    while (lectores != 0) pthread_cond_wait(&seguir,&MyMutex);

//    printf ("escribiendo\n");
    //sleep(random()%2);
    for (i=0; i<ARRLEN; i++) {
      arr[i] = num;
    }
    // Terminé de escribir.
    wannawrite = 0;

    // Hey!, despertá todos los lectores que tuvieron que dormir para que pueda escribir.
    pthread_cond_broadcast(&seguir2);
    pthread_mutex_unlock(&MyMutex);
  }
  return NULL;
}

void *lector(void *arg)
{
  int v, i, err;
  int num = *((int *)arg);
  for (;;) {
    // En este caso si pueden haber más lectores a la vez entonces no voy a bloquear toda la función con un mutex,
    // solo la bloquearé por partes.

    pthread_mutex_lock(&MyMutex); 
    lectores++;
    pthread_mutex_unlock(&MyMutex); 

    //sleep(random()%3);
    printf ("leyendo...\n");
    err = 0;
    v = arr[0];
    for (i=1; i<ARRLEN; i++) {
      if (arr[i]!=v) {
        err=1;
        break;
      }
    }
    if (err) printf("Lector %d, error de lectura\n", num);
    else printf("Lector %d, dato %d\n", num, v);

    pthread_mutex_lock(&MyMutex);
    lectores--;

    /* si pondría un unlock acá, podría pasar cualquier cosa hasta que mande 
       la señal de que yo terminé de leer y luego esperar. Por eso el unlock lo pongo al final.
       Si yo tengo el mutex por más que el otro tenga la señal y los lectores sean 0
       no puede tomar el mutex por lo tanto se queda bloqueado hasta que lo libero.  */

    /* Mando una señal que un thread terminó de leer. */
    pthread_cond_signal(&seguir);

    // Si quiere escribir, entonces me bloqueo hasta que me avise que terminó de escribir.
    while(wannawrite == 1) pthread_cond_wait(&seguir2,&MyMutex);

    // Ahora si suelto el mutex.
    pthread_mutex_unlock(&MyMutex);

  }
  return NULL;
}

int main()
{
  int i;
  pthread_t lectores[N],escritores[N];
  int arg[N];

  for (i=0; i<ARRLEN; i++) {
    arr[i] = -1;
  }
  for (i=0; i<N; i++) {
    arg[i] = i;
    pthread_create(&lectores[i], NULL, lector, (void *)&arg[i]);
   pthread_create(&escritores[i], NULL, escritor, (void *)&arg[i]);
  }

  pthread_join(lectores[0], NULL); /* Espera para siempre */
  return 0;
}
Accede o Regístrate para comentar.