关于线程同步:线程间同步之消费者与生产者案例Condition-Variable

40次阅读

共计 2440 个字符,预计需要花费 7 分钟才能阅读完成。

该程序通过一个生产者 - 消费者的例子来展现线程间的同步状况,具体形式为生产者生产一个构造体串在链表的表头上,消费者从表头取走构造体,生产者未生产或生产的曾经被拿完,则消费者须要挂起期待.

本文通过两种链表形式来进行实现,留神是在 linux 环境下编译链接:
1、生产者和消费者拜访链表的程序是 LIFO 的。

  1 #include <stdlib.h>
  2 #include <pthread.h>
  3 #include <stdio.h>
  4 
  5 struct msg {
  6     struct msg *next;
  7     int num;
  8 };
  9 
 10 struct msg *head;
 11 pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
 12 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 13 
 14 void *consumer(void *p)
 15 {   
 16     struct msg *mp;
 17     
 18     for (;;) {19         pthread_mutex_lock(&lock);
 20         while (head == NULL)
 21             pthread_cond_wait(&has_product, &lock);
 22         mp = head;
 23         head = mp->next;
 24         pthread_mutex_unlock(&lock);
 25         printf("Consume %d\n", mp->num);
 26         free(mp);
 27         sleep(rand() % 5);
 28     }
 29 }
 30 
 31 void *producer(void *p)
 32 {
 33     struct msg *mp;
 34     for (;;) {35         mp = malloc(sizeof(struct msg));
 36         mp->num = rand() % 1000 + 1;
 37         printf("Produce %d\n", mp->num);
 38         pthread_mutex_lock(&lock);
 39         mp->next = head;
 40         head = mp;
 41         pthread_mutex_unlock(&lock);
 42         pthread_cond_signal(&has_product);
 43         sleep(rand() % 5);
 44     }
 45 }
 46 

2、生产者和消费者拜访链表的程序是 FIFO 的。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 #include<unistd.h>
  5 /* 程序演示了一个生产者 - 消费者的例子, 生产者生产一个构造体串在链表的表头上, 消费者
  6  * 从表尾取走构造体。留神: 不肯定产生一次就取走一次, 尽管产生一次就唤醒一次消费者
  7  * 但有可能此时并未调度消费者线程运行, 但取走的肯定是表尾的构造体, 即最快生产剩下未被取走的即 FIFO */
  8 struct msg
  9 {   
 10     struct msg *next;
 11     int num;
 12 };
 13 
 14 struct msg *head;
 15 pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
 16 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 17 
 18 void *consumer(void *p)
 19 {
 20     struct msg *mp;
 21     for (;;)
 22     {23         pthread_mutex_lock(&lock);
 24         struct msg *t = NULL;
 25         while (head == NULL){26             pthread_cond_wait(&has_product, &lock);// 直到 producer 生产处至多一个 mp, 才会唤醒此处期待的以 has_pr    oduct 为 Condition Variable 的消费者线程
 27         }
 28         if (head->next != NULL)
 29         {
 30                 mp = head;
 31                 t = head;
 32                 while(mp->next !=NULL)
 33                 {
 34                         mp = mp->next;
 35                 }
 36                 while(t->next != mp){
 37                         t = t->next;
 38                 }
 39                 t->next = mp->next;
 40         }
 41         else
 42         {
 43             mp = head;
 44             head = mp->next;
 45         }
 46         pthread_mutex_unlock(&lock);
 47         printf("Consume %d\n", mp->num);
 48         free(mp);
 49         sleep(rand() % 5);
 50     }
 51 }
 52 
 53 void *producer(void *p)
 54 {
 55     struct msg *mp;
 56     for (;;)
 57     {58         mp = malloc(sizeof(struct msg));
 59         mp->num = rand() % 1000 + 1;
 60         printf("Produce %d \n", mp->num);
 61         pthread_mutex_lock(&lock);
 62         mp->next = head;
 63         head = mp;
 64         pthread_mutex_unlock(&lock);
 65         pthread_cond_signal(&has_product);// 唤醒以 has_product 为条件变量的 wait 中的一个线程
 66         sleep(rand() % 5);
 67     }
 68 }
 69 
 70 int main(int argc, char *argv[])
 71 {
 72     pthread_t pid, cid;
 73     srand(time(NULL));
 74     pthread_create(&pid, NULL, producer, NULL);
 75     pthread_create(&cid, NULL, consumer, NULL);
 76     pthread_join(pid, NULL);
 77     pthread_join(cid, NULL);
 78     return 0;
 79 }

在 linux 下的编译链接运行命令如下:
gcc sourcecode.c -o sourcecode -lpthread

FIFO(先生产先取用)形式执行后果如下图:

正文完
 0