头图

该程序通过一个生产者-消费者的例子来展示线程间的同步情况,具体方式为生产者生产一个结构体串在链表的表头上,消费者从表头取走结构体,生产者未生产或生产的已经被拿完,则消费者需要挂起等待.

本文通过两种链表方式来进行实现,注意是在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(先生产先取用)方式执行结果如下图:
image.png


沐小轲
9 声望0 粉丝

C++初学者