于消费者与生产者的例子 涉及到 条件变量的问题 求解啊!!!

长沙红胖子Qt
企业官方账号
博客专家认证
2011-08-09 09:38:06

#include <stdlib.h>

#include <pthread.h>

#include <stdio.h>



struct msg {

struct msg *next;

int num;

};



struct msg *head;

pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;



void *consumer(void *p)

{

struct msg *mp;

for(;;) {

pthread_mutex_lock(&lock); //A点

while (head == NULL){

pthread_cond_wait(&has_product, &lock); //B点

printf("1");

}

mp = head;

head = mp->next;

pthread_mutex_unlock(&lock);

printf("Consume %d\n", mp->num);

free(mp);

sleep(rand() % 5);

}

}



void *producer(void *p)

{

struct msg *mp;

for(;;) {

sleep(1);

mp = malloc(sizeof(struct msg));

mp->num = rand() % 1000 + 1;

printf("Produce %d\n", mp->num);

pthread_mutex_lock(&lock); //C点

mp->next = head;

head = mp;

pthread_mutex_unlock(&lock);

pthread_cond_signal(&has_product); //D点

sleep(rand() % 5);

}

}



int main(int argc, char *argv[])

{

pthread_t pid, cid;

head = NULL;

srand(time(NULL));

pthread_create(&pid, NULL, producer, NULL);

pthread_create(&cid, NULL, consumer, NULL);

pthread_join(pid, NULL);

pthread_join(cid, NULL);

return 0;

}



可能结果如下:
Produce 486
1Consume 486 //E点 请注意最前面的1
Produce 108
1Consume 108
Produce 523
Produce 476
Produce 3
Consume 3
Consume 476
Consume 523
Produce 654
1Consume 654
Produce 690
Consume 690
个人修改了下程序,本人认为过程如下:
head为0, 然后 创建2个线程, 我故意在producer线程循环里面加sleep(1),那么 就导致 consumer线程 先开始请求 lock 请求到互斥资源 然后while做无限循环 而 线程producer的C点 就由于请求不到lock 阻塞了 导致 死锁
1.说出正确过程
2.为什么E点只有1个1
(注,问题1说清楚 那么问题就出来了 所以 BD 两点请详细点)
...全文
145 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
xin_wu_hen 2011-08-09
  • 打赏
  • 举报
回复
首先,我实在无法理解你到底想实现怎样的功能。是生产者每生产一个,消费者就消费一个。还是生产者可以无限生产,消费者只要看到产品不为空,就消费呢?还有,你这结果是程序结果还是自己妄想的?再者,这段代码写的这是让人纠结。

我就对条件变量的使用来说一下,一般来说,
 while (head == NULL){

pthread_cond_wait(&has_product, &lock); //B点

printf("1");

}


这段代码是很好的,因为虽然说一般情况下pthread_cond_wait是由pthread_cond_signal唤醒的,但是有可能会出现某些特殊的情况导致pthread_cond_wait返回,所以有必要再次判断一下head的值。while不会成为死锁的原因,因为pthread_cond_wait会在has_product上等待,同时释放lock锁,何来请求等不到lock呢?一般的情况下,我们用一个锁,两个条件变量,一个用于消费者,表示有产品可消费;一个用于生产者,表示现在可以生产。不过看你的情况,由于使用链表,一个锁和一个条件变量也就可以了。但是,不知道,你具体的要求,实在无法解释啊。
BABY 2011-08-09
  • 打赏
  • 举报
回复
1.我刚开始也跟你的想法一样,会死锁,结果跑了几次,发现可以顺利跑下去,感觉很奇怪。最后查到了原因:

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。
也就是说pthread_cond_wait使得该线程等待,于是mutex就解锁了,Produce就可以拿到锁了。
2. 怎么会不只有一个1呢?难道你认为这个while循环会不断执行吗?不会的,因为前面不是有pthread_cond_wait嘛,block住了,它被唤醒的时候,head 已经不是null了。自然只会打印一次咯。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧