700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > -2-3 牛客C++项目 —— 生产者消费者模型(条件变量 信号量)

-2-3 牛客C++项目 —— 生产者消费者模型(条件变量 信号量)

时间:2020-06-28 21:40:48

相关推荐

-2-3 牛客C++项目 —— 生产者消费者模型(条件变量 信号量)

如果生产者将容器填满,需要通知消费者,

如果消费者将容器清空,需要通知生产者。

(我个人觉得如果有多个生产者和消费者,就排成队列,通知第一个就行。不知道实际情况是什么样子的)

/*生产者消费者模型(简单版)*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>struct Node{int num;struct Node*next;};//头节点struct Node*head = NULL;void *producer(void*arg){//不断的创建新的节点,添加到链表中while (1){struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));newNode->next = head;head = newNode;newNode->num = rand()%1000;printf("add node, num : %d,tid : %ld.\n",newNode->num,pthread_self());usleep(100);}return NULL;}void *customer(void*arg){while (1){//保存头节点的指针struct Node*tmp = head;head = head->next;printf("del node,num : %d,tid : %ld.\n",tmp->num,pthread_self());free(tmp);usleep(100);}return NULL;}int main(void){pthread_t ptids[5],ctids[5];for(int i = 0;i < 5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[i],NULL,customer,NULL);}for(int i = 0;i < 5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[i]);}pthread_exit(NULL);return 0;}

简单的运行的结果

解决方法:

1)互斥量

2)条件变量,实现线程的通信

如何生成 core 文件?

1、首先查看并更改 core 文件的大小设置

2、在生成的可执行文件中加入可调式信息

在生成了core 文件后,打开 gdb

3、通过使用 core-file (core filename)来打开 core 文件,查看 core 文件当中的内容。

总的来说,上面的程序存在两个问题:1)一个是多个进程操作同一个数据但是没有同步的问题

2)另一个是当 head 为null 的时候会被 costumer 访问 head-> next 的问题。

解决第一个问题:加上互斥量

在这里插入代码片

会发生死锁

解决第二个问题,加上条件变量,生产者生产完成后唤醒消费者,消费者在没有物品的时候等待。

但是依然会死锁,因为没有释放互斥量

/*条件变量的类型 pthread_cond_tint pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);int pthread_cond_destroy(pthread_cond_t *cond);int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);- 等待,调用了该函数,线程会阻塞int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);- 等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间阻塞int pthread_cond_signal(pthread_cond_t *cond);- 唤醒一个或者多个等待的线程int pthread_cond_broadcast(pthread_cond_t *cond);- 唤醒所有的等待的线程*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>//创建一个互斥量pthread_mutex_t mutex;//创建条件变量pthread_cond_t cond;struct Node{int num;struct Node*next;};//头节点struct Node*head = NULL;void *producer(void*arg){//不断的创建新的节点,添加到链表中while (1){pthread_mutex_lock(&mutex);struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));newNode->next = head;head = newNode;newNode->num = rand()%1000;printf("add node, num : %d,tid : %ld.\n",newNode->num,pthread_self());//只要生产了一个就通知消费者消费pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);usleep(100);}return NULL;}void *customer(void*arg){while (1){//保存头节点的指针pthread_mutex_lock(&mutex);struct Node*tmp = head;//判断是否有数据if(head != NULL){head = head->next;printf("del node,num : %d,tid : %ld.\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);usleep(100);}else{//没有数据,需要等待pthread_cond_wait(&cond,&mutex);//当wait 函数对这个线程进行阻塞的时候,会对这个线程进行解锁,线程不阻塞的时候,会把mutex 互斥量加上去。//这样就不至于产生影响。pthread_mutex_unlock(&mutex);// pthread_mutex_unlock(&mutex);}}return NULL;}int main(void){pthread_t ptids[5],ctids[5];pthread_mutex_init(&mutex,NULL);pthread_cond_init(&cond,NULL);for(int i = 0;i < 5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[i],NULL,customer,NULL);}for(int i = 0;i < 5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[i]);}while (1){sleep(100);}//不加 while 死循环会直接执行下面销毁互斥量的语句,那互斥量就没法用了pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);pthread_exit(NULL);// pthread_mutex_destroy(&mutex);//不能放这里,放这里直接退出了就无法执行了return 0;}

使用信号量

/*信号量的类型 sem_tint sem_init(sem_t *sem, int pshared, unsigned int value);- 初始化信号量- 参数- sem : 信号变量的地址- pshared : 0 用在线程间,非0 用在进程间- value : 信号量中的值int sem_destroy(sem_t *sem);- 释放资源int sem_wait(sem_t *sem);- 对信号量加锁,调用一次对信号量的值减一,如果为0就阻塞。int sem_trywait(sem_t *sem);int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);int sem_post(sem_t *sem);- 对信号量解锁,调用一次对信号量减一int sem_getvalue(sem_t *sem, int *sval);sem_t psem;sem_t csem;init(psem, 0, 8);init(csem, 0, 0);producer() {sem_wait(&psem);sem_post(&csem)}customer() {sem_wait(&csem);sem_post(&psem)}*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>#include<semaphore.h>//创建一个互斥量pthread_mutex_t mutex;sem_t psem;sem_t csem;struct Node{int num;struct Node*next;};//头节点struct Node*head = NULL;void *producer(void*arg){//不断的创建新的节点,添加到链表中while (1){sem_wait(&psem);pthread_mutex_lock(&mutex);struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));newNode->next = head;head = newNode;newNode->num = rand()%1000;printf("add node, num : %d,tid : %ld.\n",newNode->num,pthread_self());pthread_mutex_unlock(&mutex);sem_post(&csem);usleep(100);}return NULL;}void *customer(void*arg){while (1){//保存头节点的指针sem_wait(&csem);pthread_mutex_lock(&mutex);struct Node*tmp = head;//判断是否有数据head = head->next;printf("del node,num : %d,tid : %ld.\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);sem_post(&psem);}return NULL;}int main(void){pthread_t ptids[5],ctids[5];pthread_mutex_init(&mutex,NULL);sem_init(&psem,0,8); //表示容器空位sem_init(&csem,0,0);//表示生产的物品数for(int i = 0;i < 5;i++){pthread_create(&ptids[i],NULL,producer,NULL);pthread_create(&ctids[i],NULL,customer,NULL);}for(int i = 0;i < 5;i++){pthread_detach(ptids[i]);pthread_detach(ctids[i]);}while (1){sleep(100);}//不加 while 死循环会直接执行下面销毁互斥量的语句,那互斥量就没法用了pthread_mutex_destroy(&mutex);pthread_exit(NULL);// pthread_mutex_destroy(&mutex);//不能放这里,放这里直接退出了就无法执行了return 0;}

运行结果非常丝滑

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。