该程序通过一个生产者-消费者的例子来展示线程间的同步情况,具体方式为生产者生产一个结构体串在链表的表头上,消费者从表头取走结构体,生产者未生产或生产的已经被拿完,则消费者需要挂起等待.
本文通过两种链表方式来进行实现,注意是在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(先生产先取用)方式执行结果如下图: