1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <pthread.h>
5 #include <semaphore.h>
6 #include <time.h>
7
8 #define N 30 // 消费者或者生产者的数目
9 #define M 30 // 缓冲数目
10
11 int in = 0; // 生产者放置产品的位置,下一个空位
12 int out = 0; // 消费者取产品的位置,第一个非空位
13 int k = 0, m = 0, count = 0, a[30], products_sum = 1, count_rnd = 0, j = 0;
14
15 char buffer[M];// 缓冲初始化为0, 开始时没有产品
16 char consumer_store[1000];
17
18 sem_t empty_sem; // 同步信号量
19 sem_t full_sem; // 同步信号量
20 pthread_mutex_t mutex; // 互斥信号量
21
22 int producer_num = 1; //生产者id
23 int consumer_num = 1; //消费者id
24
25 /* 打印缓冲情况 */
26 void print(){
27 int i;
28 printf("\033[33m缓冲区中剩余产品: \033[0m\n");
29 for(i = 0; i < M; i++)
30 printf("\033[33m%c \033[0m", buffer[i]);
31 printf("\n");
32 }
33
34 void print_consumer(){
35 int i;
36 for(i = 0; i < M; i++)
37 printf("%c", consumer_store[i]);
38 printf("\n");
39 }
40
41 /* 生产者方法 */
42 void *product(){
43 sem_wait(&empty_sem);
44 pthread_mutex_lock(&mutex);
45 buffer[in] = 'A' + count;
46 count++;
47 printf("生产者 %d 生产产品 %c 放入缓冲区 %d \n",producer_num, buffer[in], in);
48 in++;
49 in=in%M;
50 producer_num++;
51 pthread_mutex_unlock(&mutex);
52 sem_post(&full_sem);
53 }
54 /* 消费者方法 */
55 void *prochase(){
56 sleep(1);
57 sem_wait(&full_sem); //获取信号量
58 pthread_mutex_lock(&mutex); //加锁
59 int n = 0, l = 0, p = 0;
60 j=(rand() % 30) + 1;
61 if(count_rnd == 0){
62 a[m] = j;
63 m++;
64 }
65 else{
66 while(n < m){
67 if(a[n] != j)
68 n++;
69 else{
70 j=(rand() % 30) + 1;
71 n = 0;
72 }
73 }
74 }
75 a[m] = j;
76 m++;
77 if(consumer_num % 2 != 0) { //奇数号消费者
78 if(consumer_num == 29) { //所有奇数号消费者都消费之后,1,3,5,7,9号产品从缓冲区撤销
79 buffer[0] = ' ';
80 buffer[2] = ' ';
81 buffer[4] = ' ';
82 buffer[6] = ' ';
83 buffer[8] = ' ';
84 }
85 if(j == 1 || j == 3 || j == 5 || j == 7 || j == 9) { //1,3,5,7,9号生产者供奇数号消费者消费
86 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
87 }
88 else if((j>1&&j<11&&j%2 == 0) || (j>10&&j<21&&consumer_num != j)) {
89 printf("消费者 %d 不能消费由生产者 %d 生产的产品!\n", consumer_num, j);
90 j=(rand() % 30) + 1;
91 while((j>1&&j<11&&j%2 == 0) || (j>10&&j<21&&consumer_num != j)){
92 j=(rand() % 30) + 1;
93 }
94 while(buffer[j-1] == ' '){
95 j=(rand() % 30) + 1;
96 }
97 a[m] = j;
98 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
99 buffer[j-1] = ' ';
100 }
101 else if(j>10&&j<21&&consumer_num == j){//11-20号生产者只供对应编号相同的消费者消费
102
103 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
104 buffer[j-1] = ' ';
105 }
106 else{ //其他任意编号的生产者被随意消费
107 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
108 buffer[j-1] = ' ';
109 }
110 }
111 else{ //偶数号消费者
112 if(j == 2 || j == 4 || j == 6 || j == 8 || j == 10){ //2,4,6,8,10号生产者被所有偶数号消费者消费
113 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
114 buffer[j-1] = ' ';
115 }
116 else if((j > 0 && j < 10 && j % 2 != 0) || (j > 10 && j < 21 && consumer_num != j)){
117 printf("消费者 %d 不能消费由生产者 %d 生产的产品!\n",consumer_num,j);
118 j=(rand() % 30) + 1;
119 while((j > 0 && j < 10 && j % 2 != 0) || (j > 10 && j < 21 && consumer_num != j)) {
120 j=(rand() % 30) + 1;
121 }
122 while(buffer[j-1] == ' '){
123 j=(rand() % 30) + 1;
124 }
125 a[m] = j;
126 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
127 buffer[j-1] = ' ';
128 }
129 else if(j>10&&j<21&&consumer_num == j) { //11-20编号的生产者供对应编号相同的消费者消费
130 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
131 buffer[j-1] = ' ';
132 }
133 else{
134 printf("\033[35;4m消费者 %d 消费由生产者 %d 生产的 %c\033[0m\n", consumer_num, j, buffer[j-1]);
135 buffer[j-1] = ' ';
136 }
137 }
138 buffer[j-1] = ' ';
139 print();
140 out++;
141 out=out % M;
142 consumer_num++;
143 count_rnd++;
144 pthread_mutex_unlock(&mutex);
145 sem_post(&empty_sem);
146 }
147
148 int main(){
149 pthread_t id1[N];
150 pthread_t id2[N];
151 int i;
152 int ret[N];
153 srand((unsigned)time(0));
154 // 初始化同步信号量
155 int ini1 = sem_init(&empty_sem, 0, M);
156 int ini2 = sem_init(&full_sem, 0, 0);
157 if(ini1 && ini2 != 0){
158 printf("sem init failed \n");
159 exit(1);
160 }
161 //初始化互斥信号量
162 int ini3 = pthread_mutex_init(&mutex, NULL);
163 if(ini3 != 0){
164 printf("mutex init failed \n");
165 exit(1);
166 }
167 // 每个生产者生产30个消息后结束运行
168 while(products_sum <= 30){
169 //创建N个生产者线程
170 for(i = 0; i < N; i++){
171 ret[i] = pthread_create(&id1[i], NULL, product, (void *)(&i));
172 if(ret[i] != 0){
173 printf("product %d creation failed \n", i);
174 exit(1);
175 }
176 }
177 //创建N个消费者线程
178 for(i = 0; i < N; i++){
179 ret[i] = pthread_create(&id2[i], NULL, prochase, NULL);
180 if(ret[i] != 0){
181 printf("prochase %d creation failed \n", i);
182 exit(1);
183 }
184 }
185 for(i = 0; i < N; i++){
186 pthread_join(id1[i], NULL);
187 pthread_join(id2[i], NULL);
188 }
189
190 printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
191 printf("完成第 %d 次生产\n",products_sum);
192 printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
193 products_sum++;
194 in = 0;
195 out = 0;
196 count = 0;
197 consumer_num = 1;
198 producer_num = 1;
199 count_rnd = 0;
200 m = 0;
201 a[30] = ' ';
202 }
203 sem_destroy(&empty_sem);
204 sem_destroy(&full_sem);
205 exit(0);
206 }