Pasar al contenido principal

Práctica 8

Versión para impresiónSend by email

Estudiamos el uso de cerrojos en la realización de un programa similar al de la práctica 7:


#define _REENTRANT

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

#define Longitud 5 
#define Cantidad 20

int Caja[Longitud];						// Se crea el Buffer
unsigned Primero = 0;						// y los contadores
unsigned Ultimo = 0;
unsigned Numero = 0;
pthread_mutex_t cerrojo = PTHREAD_MUTEX_INITIALIZER;		// Cerrojo
pthread_cond_t huecos = PTHREAD_COND_INITIALIZER;		// Condicionales
pthread_cond_t elementos = PTHREAD_COND_INITIALIZER;

/* Pone en entero en la cola, deteniéndose si no cabe */

void Pon(int X) {
  pthread_mutex_lock (&cerrojo);				// Bloqueo el cerrojo
  while (Numero == Longitud) 					// Si el buffer esta lleno
      pthread_cond_wait(&huecos, &cerrojo);			// wait
  Caja[Ultimo] = X;						// una vez salgo, introduzco X en el Buffer
  Ultimo = (Ultimo + 1) % Longitud;				// calculo la posicion del siguiente dato
  Numero++;							// y sumo un dato mas a la cuenta
  pthread_cond_signal(&elementos);				// aviso del elemento
  pthread_mutex_unlock(&cerrojo);				// desbloqueo el cerrojo
  return;
}

/* Toma un entero de la cola, deteniéndose si no hay */

void Toma(int *pX) {
  pthread_mutex_lock (&cerrojo);				// Bloqueo el cerrojo
  while (Numero == 0) 						// Si el buffer esta vacio
      pthread_cond_wait(&elementos, &cerrojo);			// me espero
  *pX = Caja[Primero];						// una vez hay algo, saco el dato
  Primero = (Primero + 1) % Longitud;				// y calculo la posicion del dato anterior
  Numero--;							// resto uno a la cuenta de datos
  pthread_cond_signal(&huecos);					// aviso del hueco
  pthread_mutex_unlock(&cerrojo);				// y desbloqueo el cerrojo
  return;
}

/* Proceso que produce enteros y los encola */

void *Productor (void *pId) {
  unsigned Id = *(unsigned*)pId;
  unsigned long Periodo = Id * 1000;
  int i;
  for (i = 1; i <= Cantidad; i++) {				// Produce Cantidad datos y los Pone en el Buffer
      Pon(i + Id);
      printf("---- Productor  %6d produce %6d\n", Id, i+Id);
      usleep(Periodo);
  }   
  return NULL;
}

/* Proceso que consume enteros */

void *Consumidor(void *pId) {
  unsigned Id = *(unsigned*)pId;
  unsigned long Periodo = Id * 1000;
  int Dato;
  int j;
  for (j = 1; j <= Cantidad; j++) {				// Consume Cantidad datos sacandolos del Buffer
      Toma(&Dato);
      printf("**** Consumidor %6d consume %6d\n", Id, Dato);
      usleep(Periodo);
  }   
  return NULL;
}

 
int main(void) {
   pthread_t productorid;
   pthread_t consumidorid;
   unsigned Id_Productor=1000;
   unsigned Id_Consumidor=5000;

   /* crear las hebras */
   pthread_create(&productorid, NULL, Productor, &Id_Productor);	// Hebra productora
   pthread_create(&consumidorid, NULL, Consumidor, &Id_Consumidor);	// Hebra consumidora

   /* esperar a que acaben las hebras */
   pthread_join(productorid, NULL);					// Esperamos a la finalizacion
   pthread_join(consumidorid, NULL);					// de ambas hebras
   exit(0);
}				        				        					 

Ejecución

merlin1@merlins1:~/Escritorio/Practicas/8$ gcc pcvc.c -o pcvc -l pthread
merlin1@merlins1:~/Escritorio/Practicas/8$ ls
pcvc pcvc.c
merlin1@merlins1:~/Escritorio/Practicas/8$ ./pcvc
---- Productor 1000 produce 1001
**** Consumidor 5000 consume 1001
---- Productor 1000 produce 1002
---- Productor 1000 produce 1003
---- Productor 1000 produce 1004
---- Productor 1000 produce 1005
**** Consumidor 5000 consume 1002
---- Productor 1000 produce 1006
---- Productor 1000 produce 1007
**** Consumidor 5000 consume 1003
---- Productor 1000 produce 1008
**** Consumidor 5000 consume 1004
---- Productor 1000 produce 1009
**** Consumidor 5000 consume 1005
---- Productor 1000 produce 1010
**** Consumidor 5000 consume 1006
---- Productor 1000 produce 1011
**** Consumidor 5000 consume 1007
---- Productor 1000 produce 1012
**** Consumidor 5000 consume 1008
---- Productor 1000 produce 1013
**** Consumidor 5000 consume 1009
---- Productor 1000 produce 1014
**** Consumidor 5000 consume 1010
---- Productor 1000 produce 1015
**** Consumidor 5000 consume 1011
---- Productor 1000 produce 1016
**** Consumidor 5000 consume 1012
---- Productor 1000 produce 1017
**** Consumidor 5000 consume 1013
---- Productor 1000 produce 1018
**** Consumidor 5000 consume 1014
---- Productor 1000 produce 1019
**** Consumidor 5000 consume 1015
---- Productor 1000 produce 1020
**** Consumidor 5000 consume 1016
**** Consumidor 5000 consume 1017
**** Consumidor 5000 consume 1018
**** Consumidor 5000 consume 1019
**** Consumidor 5000 consume 1020
merlin1@merlins1:~/Escritorio/Practicas/8$

 

Resultados Pedidos:

Explicación del funcionamiento del programa:

Comentada la explicación en el código del programa.