Search code examples
cmultithreadingproducer-consumer

How do I get a producer and a consumer thread to continuously load and unload a shared buffer?


I'd like to have two threads, a producer and a consumer, which continuously fill and empty a shared buffer. The code is a little pedantic, but I'm going to expand on it later to include actual stop conditions. Here is my situation: I have started the producer thread, it fills the buffer, passes control to the consumer, and the consumer empties the buffer. However, the consumer does not pass control back to the producer to refill the buffer. What do I have to change in order for the producer and consumer threads to continuously fill, empty, and refill the shared buffer?

Here is how my code is set up:

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

#define MAX 10
int buffer[MAX];
int count = 0;
pthread_mutex_t mutex;
pthread_cond_t dataAvailable;
pthread_cond_t spaceAvailable;

void *consumer(void *arg)
{
    while(1)
    {
            pthread_mutex_lock(&mutex);

            while(count == 0)
            {
                    pthread_cond_signal(&spaceAvailable);
                    printf("Signaling spaceAvailable\n");
                    pthread_cond_wait(&dataAvailable,&mutex);
                    printf("Consumer: resume after the wait\n");
            }

            sleep(1);

            printf("starting to empty the buffer...\n");
            int j;
            for(j = 0; j < MAX; j++)
            {
                    buffer[j] = 0;
                    printf("Consumer: buffer[%d] = %d\n",j,buffer[j]);
                    --count;
            }

            pthread_cond_signal(&spaceAvailable);
            printf("The value of count is: %d\n",count);
            pthread_cond_wait(&dataAvailable,&mutex);

        }
}


void *producer(void *arg)
{
    while(1)
    {
            pthread_mutex_lock(&mutex);

            while(count == 9)
            {
                    pthread_cond_signal(&dataAvailable);
                    printf("Signaling dataAvailable\n");
                    pthread_cond_wait(&spaceAvailable,&mutex);
                    printf("Producer: resume after wait\n");
            }

            sleep(1);


            printf("starting to load the buffer...\n");
            int j;
            for(j = 0; j < MAX; j++)
            {
                    buffer[j] = j;
                    printf("Producer: buffer[%d] = %d\n",j,buffer[j]);
                    ++count;
            }

            pthread_cond_signal(&dataAvailable);

            pthread_cond_wait(&spaceAvailable,&mutex);
        }
}


int main(int argc, char *argv[])
{
    pthread_t thread;

    pthread_create(&thread,0,producer,NULL);
    pthread_create(&thread,0,consumer,NULL);
    pthread_exit(0);

}

This is what my output looks like:

starting to load the buffer...
Producer: buffer[0] = 0
Producer: buffer[1] = 1
Producer: buffer[2] = 2
Producer: buffer[3] = 3
Producer: buffer[4] = 4
Producer: buffer[5] = 5
Producer: buffer[6] = 6
Producer: buffer[7] = 7
Producer: buffer[8] = 8
Producer: buffer[9] = 9
starting to empty the buffer...
Consumer: buffer[0] = 0
Consumer: buffer[1] = 0
Consumer: buffer[2] = 0
Consumer: buffer[3] = 0
Consumer: buffer[4] = 0
Consumer: buffer[5] = 0
Consumer: buffer[6] = 0
Consumer: buffer[7] = 0
Consumer: buffer[8] = 0
Consumer: buffer[9] = 0
The value of count is: 0

I'd like to have the Producer and Consumer statements to print every second. What would I have to fix in order to make that happen?


Solution

  • Use semaphore to synchronize (signal the other thread when one has executed the iteration):

    Semaphore s1, s2;
    
    Producer:
    P(&s1)
    // do your operations
    print()
    V(&s2) //unlock the consumer thread
    
    Consumer:
    P(&s2)
    // do your operations
    print()
    V(&s1) //unlock the producer thread
    

    Just make sure you do it in such a way to avoid any deadlock.