您的位置:首页 > 运维架构 > Linux

linux下实现生产者-消费者问题

2017-02-20 17:50 459 查看
生产者(producer)和消费者(consumer)问题是并发处理中最常见的一类问题,是一个多线程同步问题的经典案例。        可以这样描述这个问题,有一个或者多个生产者产生某种类型的数据,并放置在固定大小的缓冲区中,一个消费者从缓冲区中取数据,每次取一项,系统必须保证对缓冲区的重复操作,任何时候,只有一个生产者或者消费者可以访问缓冲区;同时,消费者只能在缓冲区不为空的时候从缓冲区中读数据,生产者只能在缓冲区不为满的时候向缓冲区写入数据。上面的问题总结起来有两点:       第一是缓冲区的互斥访问问题,任意时刻最多只能有一个线程访问缓冲区,Linux下可以使用互斥量pthread_mutex_t对访问缓冲区的临界区代码进行保护。      第二是生产者和消费者对缓冲区访问的同步问题,生产者在缓冲区满时不能向缓冲区中写入数据,同时消费者在缓冲区空时不能读取数据,这里采用条件变量来对缓冲区进行同步。实现代码如下:#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <assert.h>pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;typedef struct _node{int data;struct _node *next;}node_t, *node_p, **node_pp;node_p alloc_node(int data){node_p _n = (node_p)malloc(sizeof(node_t));if(_n == NULL){perror("malloc");return NULL;}_n->data = data;_n->next = NULL;return _n;}void del_node(node_p _n){assert(_n);free(_n);}int is_empty(node_p list){assert(list);if(list->next){return 0;}elsereturn 1;}void show_list(node_p list){assert(list);node_p start = list->next;while(start){printf("%d\n",start->data);start = start->next;}printf("\n");}void init_list(node_pp _h){*_h = alloc_node(0);}void Push(node_p list, int data){assert(list);node_p new_node = alloc_node(data);new_node->next = list->next;list->next = new_node;}void Pop(node_p list, int *data){assert(list);assert(data);if(is_empty(list)){printf("list is empty\n");}node_p _n = list->next;list->next = _n->next;*data = _n->data;del_node(_n);}void destory_list(node_p list){assert(list);int data = 0;while(!is_empty(list)){Pop(list, &data);}del_node(list);}void test_list(node_p head){int i = 0;for( ; i<10; i++){Push(head, i);sleep( 1 );show_list(head);}int data = 0;for(; i>=5; i--){Pop(head, &data);sleep(1);show_list(head);}}void *thread_product(void* arg){node_p head = (node_p)arg;while(1){usleep(100621);int data = rand()%10000;pthread_mutex_lock(&mylock);Push(head, data);pthread_mutex_unlock(&mylock);pthread_cond_signal(&mycond);printf("product data is: %d\n", data);}}void *thread_consumer(void* arg){node_p head = (node_p)arg;int data = 0;while(1){pthread_mutex_lock(&mylock);while(is_empty(head)){pthread_cond_wait(&mycond, &mylock);}Pop(head, &data);pthread_mutex_unlock(&mylock);printf("consumer done, data is: %d\n",data);}}int main(){node_p head = NULL;init_list(&head);//test_list(head);pthread_t tid1, tid2;pthread_create(&tid1, NULL, thread_product, (node_p)head);pthread_create(&tid2, NULL, thread_consumer, (node_p)head);pthread_join(tid1, NULL);pthread_join(tid2, NULL);destory_list(head);show_list(head);pthread_mutex_destroy(&mylock);pthread_cond_destroy(&mycond);show_list(head);//sleep(1);return 0;}实现结果如下图所示:因为我在编程时用了产生随机数的函数rand(),所以数字产生是随机的。
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: