C - 生产者/消费者死锁问题

时间:2010-11-05 19:02:39

标签: c deadlock semaphore producer-consumer

我正在尝试使用有界缓冲区中的生产者/消费者线程。缓冲区长度为5.我有1个互斥锁和2个信号量,空白以缓冲区大小开始,为满,从0开始。

当我在最后运行没有sleep()的代码时,它会不断产生,直到缓冲区完全充满,消耗直到它为空,所以输出如下所示:

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.

但是,当我在最后使用sleep()运行时,会打印出来:

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

然后它似乎锁定了,但我不确定为什么它的行为方式无论睡眠是否存在。有什么建议?我的主要方法基本上只是使一些声明然后创建1个生成的线程和1个消费,这些方法在下面。

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);

        }
}

4 个答案:

答案 0 :(得分:3)

sleep()的参数是睡眠的秒数。 rand()返回一个介于0和RAND_MAX之间的整数(通常为32767或2 31 -1),当你将其乘以10时,你的睡眠数量非常大时间你没有死锁,只是睡了很长时间。

答案 1 :(得分:2)

我不知道这是否是你死锁的原因,但你必须小心它们受到中断的sem_t功能,特别是由于IO等等。

永远不要忽略系统功能的返回。在这里,您必须检查退货,然后errno查看EINTR

然后,我不知道你是否被迫使用sem_t,但我认为更自然的是使用pthread_cond_t。无论如何你都有一个互斥体,所以这更容易适应。 pthread_cond_t作为pthread_mutex_t函数永远不会被中断。

答案 2 :(得分:1)

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

这可能是因为每个线程给出的~30 ms时间片足以让生产者在上下文切换有机会发生之前生成所有内容。

答案 3 :(得分:0)

我假设你的两个线程都有相同的优先级?这是在具有多个内核的机器上,还是只有一个?只是发信号通知信号量不会抢占你当前的线程,因此当前线程应该继续进行直到它的切片到期为止。

另外,我肯定会在发出互斥锁信号之前解锁互斥锁。