×
Crocus
공부한 내용을 정리하는 블로그로 시작한
Crocus는 2014년 1월 14일 부터 시작하여
현재 월 6만명, 총 2,045,665명의 방문자 수를 기록하고 있습니다.
Donation
이제 많은 사용자들이 이용하는 만큼
더 다양한 서비스 개발/제공을 위해 후원금을 모금하고자 합니다.
후원을 해주시는 분들은 Donators 명단에 성명, 후원금을 기입해드리며
Crocus 블로그가 아닌 다른 곳에 정리해둔 저만의 내용을 공유해 드리고자 합니다.
Account
예금주 : 고관우
신한은행 : 110-334-866541
카카오뱅크 : 3333-01-7888060

👉 후원 페이지 바로가기 Donators
익명 : 5000원(Crocus응원합니다.)
busyhuman: 5000원(유용한 지식 감사합니다.)
익명 : 5000원(알고리즘 학습러)
반응형

- 본 내용은 Linux (Ubuntu 14.04 lts)를 기반으로 제작되었습니다. -





목록

1. Producer and Consumer

2. Mutex Condition

3. Mutex Condition Producer and Consumer






1. Producer and Consumer


흔히 세마포어, 뮤텍스를 학습하다 보면 프로듀서 컨슈머라는 대표적인 예제를 통해 대해 알아보곤 한다.


왜 Producer and Consumer을 이용하나?


프로듀서 컨슈머는 하나의 Buffer을 공유한다.


우리가 뮤텍스, 세마포어를 배우는 이유도 Unsafe Region을 동기화된 지역으로 (Critical Section으로 만들어서)


변경시켜 코드상의 문제 및 실행상의 문제를 해결하기 위함이다.


이번에 알아볼 프로듀서 컨슈머의 예제 코드가 돌아가는 방식은 다음과 같다.


0. 초기 프로듀서의 세마포어는 1개로 시작하고, 컨슈머의 세마포어는 0개로 시작한다.


1. 생산된 아이템이 0개라면 프로듀서는 프로듀서의 세마포어를 P를 통해 소비하여 제작에 들어간다.


2. 프로듀서가 생산을 마치면 프로듀서의 세마포어를 V를 통해 1개 늘리는 것이 아닌,

컨슈머의 V를 통해 1개를 늘려 컨슈머가 깨어나도록 한다.


3. 다음 프로듀서가 다시 아이템을 생산하려해도 이미 프로듀서의 세마포어가 0개이므로,

생산을 하러 갈 수 없고, sleep상태에 접어든다. 


4. 이때 컨슈머는 세마포어의 수가 0개에서 1개가 되었으니, 아이템을 소비한다.

그리고 나서 컨슈머의 V를 해주는 것이 아닌 프로듀서의 V를 해줌으로써 아이템을 생산 할 수 있도록한다.





세마포어(Semaphore)를 이용한 Producer and Consumer


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
 
// Producer 세마포어, Consumer 세마포어 선언
sem_t P,C; 
int item;
 
void* threadFuncP(void* arg)
{
    int i;
    
    for (i = 0; i < 100; i++)
    {
        // Producer에 P기능을 수행
        sem_wait(&P);
        
        // Critical Section
        item = i;
        printf("Producer에서 아이템 생산 :: %d\n",item);
 
        // Consumer에 V기능을 수행
        sem_post(&C);
    }
 
    return 0;
}
 
void* threadFuncC(void* arg)
{
    int i, get;
 
    for (i = 0; i < 100; i++)
    {
        // Consumer에 P기능을 수행
        sem_wait(&C);
 
        // Critical Section
        get = item;
        printf("Consumer에서 아이템 소비 :: %d\n",get);
 
        // Producer에 V기능을 수행
        sem_post(&P);
    }
 
    return 0;
}
 
int main()
{
    // Producer, Consumer 스레드 선언
    pthread_t threadP, threadC;
 
    // 세마포어 초기화(Producer 세마포어 :: 1, Consumer 세마포어 :: 0)
    sem_init(&P, 01);
    sem_init(&C, 00);
 
    // 스레드 생성
    pthread_create(&threadP, NULL, threadFuncP, NULL);
    pthread_create(&threadC, NULL, threadFuncC, NULL);
 
    // 스레드 조인
    pthread_join(threadP, NULL);
    pthread_join(threadC, NULL);
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus










3. 뮤텍스(Mutex)를 이용한 Producer and Consumer


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <pthread.h>
 
 
// 프로듀서 컨슈머 뮤텍스 선언
pthread_mutex_t mutexP = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexC = PTHREAD_MUTEX_INITIALIZER;
 
int item;
 
void *threadFuncP(void* arg)
{
    int i;
 
    for(i = ; i < 100; i ++)
    {
        pthread_mutex_lock(&mutexP);
 
        // Critical Section
        item = i;
        printf("Producer에서 아이템 생산 :: %d\n",item);
 
        pthread_mutex_unlock(&mutexC);
    }
 
    return 0;
}
 
void *threadFuncC(void* arg)
{
    int i, get;
 
    for (i = 0; i < 100; i++)
    {
        pthread_mutex_lock(&mutexC);
 
        // Critical Section
        get = item;
        printf("Consumer에서 아이템 소비 :: %d\n",get);
 
        pthread_mutex_unlock(&mutexP);
    }
 
    return 0;
}
 
 
int main()
{
    // 프로듀서 컨슈머 스레드 선언
    pthread_t threadP, threadC;
 
    // 컨슈머는 아이템이 없을 때 행동하면 안되기에 초기에 lock으로 시작한다.
    pthread_mutex_lock(&mutexC);
 
    pthread_create(&threadP, NULL, threadFuncP, NULL);
    pthread_create(&threadC, NULL, threadFuncC, NULL);
 
    pthread_join(threadP, NULL);
    pthread_join(threadC, NULL);
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus







2. Mutex Condition


뮤텍스 컨디션은 다음 링크에서 자세히 설명되어있기에 설명은 생략한다.


http://www.crocus.co.kr/526


이를 이용한 프로듀서 컨슈머를 제작해보자.




3. 뮤텍스 컨디션(Mutex Condition)를 이용한 Producer and Consumer


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>
#include <pthread.h>
 
// 뮤텍스 및 컨디션 선언
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
 
int item = -1;
 
void* threadFuncP(void* arg)
{
    int i;
 
    for (i = 0; i < 100; i++)
    {
        // mutex lock
        pthread_mutex_lock(&mutex);
 
        // critical section
        item = i;
        printf("Producer가 아이템을 생산 :: %d\n", item);
 
        // signal 을 통해 consumer를 깨울 준비를 한다.
        pthread_cond_signal(&cond);
 
        // producer은 아이템을 생산하였으니 다시 기다린다.
        pthread_cond_wait(&cond, &mutex);
 
        // wait가 끝이나면 unlock을 하고 for문을 준비한다.
        pthread_mutex_unlock(&mutex);
    }
 
    return 0;
}
 
void* threadFuncC(void* arg)
{
    int i, get;
 
    for (i = 0; i < 100; i++)
    {
        // mutex lock
        pthread_mutex_lock(&mutex);
 
        //critical section
        // item이 아직 도착하지 않았을 때(조건)
        // wait를 통해 기다린다.
        while (item == -1)
            pthread_cond_wait(&cond, &mutex);
 
        get = item;
        printf("Consumer이 아이템을 소비 :: %d\n", get);
        // 아이템을 소비하면 -1로 표현
        item = -1;
 
        // signal을 통해 producer를 깨울 준비를 한다.
        pthread_cond_signal(&cond);
 
        // 걸려있던 lock을 풀고 for문을 준비한다.
        pthread_mutex_unlock(&mutex);
    }
 
    return 0;
}
 
int main()
{
    pthread_t threadP, threadC;
 
    pthread_create(&threadP, NULL, threadFuncP, NULL);
    pthread_create(&threadC, NULL, threadFuncC, NULL);
 
    pthread_join(threadP, NULL);
    pthread_join(threadC, NULL);
 
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus







































반응형