Pergunta

I'm trying to work with producer/consumer threads in a bounded buffer. The buffer length is 5. I have 1 mutex and 2 semaphores, empty which starts out at the size of the buffer, and full, which starts out at 0.

When I run my code without sleep() at the end, it continually produces until the buffer is completely fully, the consumes until it's empty, so the output looks like this:

Placed 1 in the buffer at position 0.
Placed 2 in the buffer at position 1.
Placed 3 in the buffer at position 2.
Placed 4 in the buffer at position 3.
Placed 5 in the buffer at position 4.
The buffer now contains 0 at position 0.
The buffer now contains 0 at position 1.
The buffer now contains 0 at position 2.
The buffer now contains 0 at position 3.
The buffer now contains 0 at position 4.

However, when i run with sleep() at the end, it prints out:

Placed 1 in the buffer at position 0.
The buffer now contains 0 at position 0.

Then it appears to lock up, but I'm not really sure why it behaves the way it does regardless of whether or not sleep is there. Any suggestions? My main method essentially just makes some declarations then creates 1 thread to produce and 1 to consume, those methods are below.

void *producer()
{
        int k = 0; //producer index
        while (1)
        {
                sem_wait(&empty);
                pthread_mutex_lock(&mutex);
                buffer[k] = k+1;
                sem_post(&full);
                pthread_mutex_unlock(&mutex);
                printf("Placed %d in the buffer at position %d.\n", buffer[k], k);
                k = (k + 1) % BUFFER_SIZE;
                sleep(rand() * 10);
        }
}

void *consumer()
{
        int j = 0;   //consumer index
        while(1)
        {
                sem_wait(&full);
                pthread_mutex_lock(&mutex);
                buffer[j] = 0;
                sem_post(&empty);
                pthread_mutex_unlock(&mutex);
                printf("The buffer now contains %d at position %d.\n", buffer[j], j);
                j = (j + 1) % BUFFER_SIZE;
                sleep(rand() * 10);

        }
}
Foi útil?

Solução

The parameter to sleep() is the number of seconds to sleep for. rand() returns an integer between 0 and RAND_MAX (typically 32767 or 231-1), and when you multiply that by 10, you're sleeping for an absurdly large amount of time. You're not deadlocking, just sleeping for a very long time.

Outras dicas

I don't know if that is the reason for your deadlock, but you have to be careful with sem_t functions they are subject to interrupts, in particular due to IO and things like that.

Never ignore returns from system functions. Here, you'd have to check the return and then errno for EINTR.

Then, I don't know if you are forced to use sem_t, but I think more natural here would be to use a pthread_cond_t. You have a mutex anyhow, so this would fit more easily. pthread_cond_t as pthread_mutex_t functions will never be interrupted.

Do you have any idea why when I don't include sleep it always produces and consumes in blocks instead of every other?

Thats probably because the ~30 ms time slice each thread is given is more than enough to have the producer produce everything, before a context switch had a chance to occur.

I assume both your threads have the same priority? And is this on a machine with multiple cores, or just one? Just signaling a semaphore will not preempt your current thread, so it is to be expected for the current thread to carry on until its slice expires.

Also, I would definitely unlock the mutex before signaling the mutex.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top