gpt4 book ai didi

c - 使用条件变量多线程时出现意外行为

转载 作者:行者123 更新时间:2023-12-04 16:27:46 25 4
gpt4 key购买 nike

在下面的代码中:

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

pthread_mutex_t mtx;
pthread_cond_t cond;

int how_many = 10;
int pool = 0;

void * producer(void * ptr)
{
while (how_many > 0)
{
pthread_mutex_lock(&mtx);
printf("producer: %d\n", how_many);
pool = how_many;
how_many--;
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond);
}

pthread_exit(0);
}

void * consumer(void * ptr)
{
while (how_many > 0)
{
pthread_mutex_lock(&mtx);
pthread_cond_wait(&cond, &mtx);
printf("consumer: %d\n", pool);
pool = 0;
pthread_mutex_unlock(&mtx);
}
pthread_exit(0);
}

int main(int argc, char ** argv)
{
pthread_t prod, cons;
pthread_mutex_init(&mtx, 0);
pthread_cond_init(&cond, 0);
pthread_create(&cons, 0, consumer, 0);
pthread_create(&prod, 0, producer, 0);
pthread_join(prod, 0);
pthread_join(cons, 0);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mtx);
return 0;
}

我没有得到预期的输出。

预期输出:

Producer:10    
Consumer:10
Producer:9
Consumer:9
Producer:8
Consumer:8
Producer:7
Consumer:7
Producer:6
Consumer:6
Producer:5
Consumer:5
Producer:4
Consumer:4
Producer:3
Consumer:3
Producer:2
Consumer:2
Producer:1
Consumer:1

实际输出:

producer: 10    
producer: 9
producer: 8
producer: 7
producer: 6
producer: 5
producer: 4
producer: 3
producer: 2
producer: 1

另外,在消费者方面,如果我们锁定并等待信号,生产者如何获得锁定以便他可以向消费者发送信号?

  1. 会死锁吗?
  2. 我的 friend 建议像 pthread_cond_wait(&cond, &mtx);实际上会解锁资源,直到它收到生产者的信号。这是真的吗?

最佳答案

互斥体仅提供互斥(如果使用得当);它们本身并不提供阻止特定事件发生或直到满足特定条件的机制。这就是条件变量的用途(如果你想更深入一点,还有信号量)。

您的代码允许消费者等待生产者进行生产,但不让生产者等待消费者在继续之前进行消费。如果您希望两个线程交替,那么您需要第二个条件变量来为后者提供。

Also, in consumer side, If we lock and wait for the signal, how the producer can get the lock so that he can send the signal to the consumer?

  1. will it be dead lock?

  2. My friends are suggesting like pthread_cond_wait(&cond, &mtx); would actually unlock the resources until it gets the signal from producer. is that true?

您是否考虑过阅读文档,而不是询问您的 friend 或互联网?这是手册页描述它的方式:

These functions atomically release mutex [...]. Upon successful return, the mutex shall have been locked and shall be owned by the calling thread.

也就是说,调用 pthread_cond_wait() 的线程在等待时不会锁定互斥锁,但会在返回之前重新获取互斥锁(这可能会导致线程接收互斥锁之间存在不确定的延迟)信号和函数调用返回)。

此外,请始终记住,线程可能会因等待条件变量而被虚假唤醒。唤醒时检查条件是否确实满足非常重要,如果不满足则继续等待。

这是构建生产者的一种方法:

void * producer(void * ptr)
{
pthread_mutex_lock(&mtx);
while (how_many > 0)
{
if (pool == 0) {
printf("producer: %d\n", how_many);
pool = how_many;
how_many--;
pthread_cond_signal(&full_cond);
}
pthread_cond_wait(&empty_cond, &mtx);
}
pthread_mutex_unlock(&mtx);

pthread_exit(0);
}

请注意:

  1. 我已经重命名了您原来的条件变量并引入了一个新条件变量。现在有 full_cond,表示池(容量为 1)已满,还有 empty_cond,表示池为空。
  2. 整个循环由互斥体保护。这很好,因为它执行一个 pthread_cond_wait() 命名该互斥体;当生产者等待时,其他线程将能够运行。互斥体确保对 how_manypool 变量的访问正确同步。
  3. 循环通过测试来验证它是否确实为空,从而防止虚假唤醒。如果没有,它会循环回到等待,而不做任何其他事情。
  4. 为了使其正常工作,消费者需要进行相应的更改(留给您练习)。

关于c - 使用条件变量多线程时出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30459982/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com