Il problema del produttore-consumatore (conosciuto anche con il nome di problema del buffer limitato o, in inglese, bounded-buffer problem) è un problema di sincronizzazione dei processi in cui due processi, un produttoreP (in inglese producer) e un consumatoreC (in inglese consumer), condividono un bufferbuffer comune di dimensione fissata BUFFER_SIZE.
Il produttore ha una variabile localenext_produced contenente il nuovo elemento da produrre e, finché il buffer è pieno, non fa niente, effettuando una busy waiting; una volta che si libera, inserisce l’elemento next_produced nel buffer alla posizione in e aggiorna il valore di questo indice:
item next_produced;while (true) { // Produzione di un elemento in next_produced while (((in + 1) % BUFFER_SIZE) == out); // Busy waiting buffer[in] = next_produced; in = (in + 1) % BUFFER_SIZE;}
Viceversa, il consumatore ha una variabile localenext_consumed contenente il nuovo elemento da consumare e, finché il buffer è vuoto, non fa niente, effettuando una busy waiting; una volta che si riempie, preleva l’elemento next_consumed dal buffer alla posizione out e aggiorna il valore di questo indice:
item next_consumed;while (true) { while (in == out); // Busy waiting next_consumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; // Consumazione dell'elemento in next_consumed}
Questa soluzione consentiva la presenza contemporanea di non più di BUFFER_SIZE - 1 elementi a causa della definizione dell’array circolare. Si supponga di voler modificare l’algoritmo per rimediare a questa carenza e sfruttare anche l’ultimo elemento: una possibilità consiste nell’aggiungere una variabile interacounter, inizializzata a 0, che si incrementa ogniqualvolta s’inserisce un nuovo elemento nel buffer e si decrementa ogniqualvolta si preleva un elemento dal buffer. Il codice per il produttore si può modificare come segue:
item next_consumed;int counter = 0;while (true) { // Produzione di un elemento in next_produced while (counter == BUFFER_SIZE); // Busy waiting buffer[in] = next_produced; in = (in + 1) % BUFFER_SIZE; counter++;}
Il codice per il consumatore, invece, si può modificare come segue:
item next_consumed;int counter;while (true) { while (counter == 0); // Busy waiting next_consumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; counter--; // Consumazione dell'elemento in next_consumed}