1// producer_consumer.c
2// μμ°μ-μλΉμ ν¨ν΄ (κ²½κ³ λ²νΌ)
3#include <stdio.h>
4#include <stdlib.h>
5#include <pthread.h>
6#include <unistd.h>
7#include <stdbool.h>
8#include <time.h>
9
10#define BUFFER_SIZE 5
11#define NUM_ITEMS 20
12
13// κ²½κ³ λ²νΌ
14typedef struct {
15 int buffer[BUFFER_SIZE];
16 int count; // νμ¬ μμ΄ν
μ
17 int in; // λ€μ μ½μ
μμΉ
18 int out; // λ€μ μΆμΆ μμΉ
19
20 pthread_mutex_t mutex;
21 pthread_cond_t not_full; // λ²νΌκ° κ°λ μ°¨μ§ μμ
22 pthread_cond_t not_empty; // λ²νΌκ° λΉμ΄μμ§ μμ
23
24 bool done; // μμ° μλ£ νλκ·Έ
25} BoundedBuffer;
26
27BoundedBuffer* buffer_create(void) {
28 BoundedBuffer* bb = malloc(sizeof(BoundedBuffer));
29 bb->count = 0;
30 bb->in = 0;
31 bb->out = 0;
32 bb->done = false;
33
34 pthread_mutex_init(&bb->mutex, NULL);
35 pthread_cond_init(&bb->not_full, NULL);
36 pthread_cond_init(&bb->not_empty, NULL);
37
38 return bb;
39}
40
41void buffer_destroy(BoundedBuffer* bb) {
42 pthread_mutex_destroy(&bb->mutex);
43 pthread_cond_destroy(&bb->not_full);
44 pthread_cond_destroy(&bb->not_empty);
45 free(bb);
46}
47
48void buffer_put(BoundedBuffer* bb, int item) {
49 pthread_mutex_lock(&bb->mutex);
50
51 // λ²νΌκ° κ°λ μ°ΌμΌλ©΄ λκΈ°
52 while (bb->count == BUFFER_SIZE) {
53 printf("[μμ°μ] λ²νΌ κ°λ μ°Έ. λκΈ°...\n");
54 pthread_cond_wait(&bb->not_full, &bb->mutex);
55 }
56
57 // μμ΄ν
μ½μ
58 bb->buffer[bb->in] = item;
59 bb->in = (bb->in + 1) % BUFFER_SIZE;
60 bb->count++;
61
62 printf("[μμ°μ] μμ΄ν
%d μμ° (λ²νΌ: %d/%d)\n",
63 item, bb->count, BUFFER_SIZE);
64
65 // μλΉμμκ² μλ¦Ό
66 pthread_cond_signal(&bb->not_empty);
67
68 pthread_mutex_unlock(&bb->mutex);
69}
70
71int buffer_get(BoundedBuffer* bb, int* item) {
72 pthread_mutex_lock(&bb->mutex);
73
74 // λ²νΌκ° λΉμ΄μκ³ μμ° μλ£ μλλ©΄ λκΈ°
75 while (bb->count == 0 && !bb->done) {
76 printf("[μλΉμ] λ²νΌ λΉμ΄μμ. λκΈ°...\n");
77 pthread_cond_wait(&bb->not_empty, &bb->mutex);
78 }
79
80 // λ²νΌκ° λΉμ΄μκ³ μμ° μλ£λ©΄ μ’
λ£
81 if (bb->count == 0 && bb->done) {
82 pthread_mutex_unlock(&bb->mutex);
83 return 0; // λ μ΄μ μμ΄ν
μμ
84 }
85
86 // μμ΄ν
μΆμΆ
87 *item = bb->buffer[bb->out];
88 bb->out = (bb->out + 1) % BUFFER_SIZE;
89 bb->count--;
90
91 printf("[μλΉμ] μμ΄ν
%d μλΉ (λ²νΌ: %d/%d)\n",
92 *item, bb->count, BUFFER_SIZE);
93
94 // μμ°μμκ² μλ¦Ό
95 pthread_cond_signal(&bb->not_full);
96
97 pthread_mutex_unlock(&bb->mutex);
98 return 1; // μ±κ³΅
99}
100
101void buffer_set_done(BoundedBuffer* bb) {
102 pthread_mutex_lock(&bb->mutex);
103 bb->done = true;
104 pthread_cond_broadcast(&bb->not_empty); // λͺ¨λ μλΉμ κΉ¨μ
105 pthread_mutex_unlock(&bb->mutex);
106}
107
108// μμ°μ μ€λ λ
109void* producer(void* arg) {
110 BoundedBuffer* bb = (BoundedBuffer*)arg;
111
112 for (int i = 1; i <= NUM_ITEMS; i++) {
113 usleep((rand() % 500) * 1000); // 0~500ms λκΈ°
114 buffer_put(bb, i);
115 }
116
117 printf("[μμ°μ] μμ° μλ£\n");
118 buffer_set_done(bb);
119
120 return NULL;
121}
122
123// μλΉμ μ€λ λ
124void* consumer(void* arg) {
125 BoundedBuffer* bb = (BoundedBuffer*)arg;
126 int item;
127
128 while (buffer_get(bb, &item)) {
129 usleep((rand() % 800) * 1000); // 0~800ms μ²λ¦¬ μκ°
130 }
131
132 printf("[μλΉμ] μλΉ μλ£\n");
133 return NULL;
134}
135
136int main(void) {
137 srand(time(NULL));
138
139 BoundedBuffer* bb = buffer_create();
140
141 pthread_t prod;
142 pthread_t cons[2];
143
144 // μμ°μ 1λͺ
145 pthread_create(&prod, NULL, producer, bb);
146
147 // μλΉμ 2λͺ
148 pthread_create(&cons[0], NULL, consumer, bb);
149 pthread_create(&cons[1], NULL, consumer, bb);
150
151 // λκΈ°
152 pthread_join(prod, NULL);
153 pthread_join(cons[0], NULL);
154 pthread_join(cons[1], NULL);
155
156 buffer_destroy(bb);
157 printf("\nνλ‘κ·Έλ¨ μ’
λ£\n");
158
159 return 0;
160}