C - 生产者/消费者死锁问题
我正在尝试在有界缓冲区中使用生产者/消费者线程。缓冲区长度为 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);
}
}
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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
sleep()
的参数是休眠的秒数。rand()
返回 0 到RAND_MAX
之间的整数(通常为 32767 或 231-1),当您将其乘以 10 时,您可以得到我们的睡眠时间长得离谱。你并没有陷入僵局,只是睡了很长时间。The parameter to
sleep()
is the number of seconds to sleep for.rand()
returns an integer between 0 andRAND_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.我不知道这是否是死锁的原因,但您必须小心 sem_t 函数,它们容易受到中断,特别是由于 IO 和类似的事情。
永远不要忽略系统函数的返回。在这里,您必须检查返回结果,然后检查
errno
是否为EINTR
。然后,我不知道您是否被迫使用
sem_t
,但我认为这里更自然的是使用pthread_cond_t
。无论如何,你有一个互斥体,所以这会更容易适合。pthread_cond_t
作为pthread_mutex_t
函数永远不会被中断。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
forEINTR
.Then, I don't know if you are forced to use
sem_t
, but I think more natural here would be to use apthread_cond_t
. You have a mutex anyhow, so this would fit more easily.pthread_cond_t
aspthread_mutex_t
functions will never be interrupted.你知道为什么当我不包括 sleep 时,它总是以块的形式生成和消耗,而不是每隔一个块吗?
这可能是因为每个线程给出的大约 30 毫秒的时间片足以满足让生产者在上下文切换有机会发生之前生产出所有内容。
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.