¡Esta es una revisión vieja del documento!
Semáforos
Un semáforo es un contenedor de tickets. En él se pueden depositar un ticket con sem_post y extraer un ticket con sem_wait. La garantía es que si sem_wait no encuentra tickets entonces no retorna hasta que algún thread invoque sem_post para depositar un ticket.
Un semáforo se manipula con las siguientes funciones:
#include <semaphore.h> sem_t sem; sem_init(&sem, 0, tickets_iniciales); sem_post(&sem); sem_wait(&sem);
La siguiente es una implementación correcta de la estructura Buffer del productor/consumidor.
/* Versión correcta */
typedef struct {
int size;
Cuadro **array;
int in, out;
sem_t empty, full;
} Buffer;
Buffer *nuevoBuffer(int size) {
Buffer *buf= (Buffer*)malloc(sizeof(Buffer));
buf->size= size;
buf->array= (Cuadro**)malloc(size*sizeof(Cuadro*));
buf->in= buf->out= 0;
sem_init(&buf->empty, 0, size);
sem_init(&buf->full, 0, 0);
return buf;
}
void put(Buffer *buf, Cuadro *cuadro) {
sem_wait(&buf->empty);
buf->array[buf->in]= cuadro;
buf->in= (buf->in+1) % buf->size;
sem_post(&buf->full);
}
Cuadro *get(Buffer *buf) {
Cuadro *cuadro;
sem_wait(&buf->full);
cuadro= buf->array[buf->out];
buf->out= (buf->out+1) % buf->size;
sem_post(&buf->empty);
return cuadro;
}
Ejercicio: múltiples productores y múltiples consumidores
Hay muchos problemas que se pueden paralelizar usando la abstracción productor/consumidor. En ellos la solución es la misma de arriba. Solo cambia el código del productor, del consumidor y los ítemes que se depositan en el Buffer. Pero el código del buffer es el mismo.
El problema del productor/consumidor se puede generalizar a múltiples productores y múltiples consumidores que comparten el mismo buffer. Muestre que en este caso el código para depositar y extraer elementos de buffer puede sufrir de data-races. Corrija el código usando un semáforo o mutex adicional.
