반응형

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



세마포어를 이용하여, 프로듀서와 컨슈머를 제작해 본다.


실생활의 예로는, 동영상을 볼 때, 버퍼링을 통해 일정 범위를 받아두고 시청자가 시청할 수 있게되고,


네이버, 다음, 구글 지도처럼 버퍼링을 통해 일정 부분을 계속 볼 수 있게 하는 방식들이 있다.


 

( 세마포어를 이용하지 않고, 스레드 및 공유변수를 이용하여 만든 코드는 아래 주소에 있다.

http://www.crocus.co.kr/318 )


알고리즘은 다음과 같다.


Producer Algorithm

- produce 세마포어는 처음 생산해야 하니 1로 초기화, 


1. producer 스레드는 produce 세마포어를 wait (P) 한다.

 - consumer 스레드에서 produce 세마포어를 post (V) 해주기 전 까지는

 - producer 스레드에서 for문을 돌다가 sem_wait(&produce);에서 sleep하게 된다.

 

2. 아이템 하나를 공유변수 storagebox에 넣어준다.


3. producer 스레드는 컨슘 세마포어를 post (V) 한다.


Consumer Algorithm

- consume 세마포어는 처음에 가져갈 것이 없으니 0으로 초기화 한다.


1. consumer 스레드는 consume 세마포어를 wait (P) 한다.

 - producer 스레드에서 consume 세마포어를 post (V) 해주기 전 까지는

 - consumer 스레드에서 for문을 돌다가 sem_wait(&consume);에서 sleep하게 된다.


2. 공유변수 storagebox에서 아이템 변수로 받아낸다.


3. consumer 스레드는 produce 세마포어를 post (V) 해준다.




소스 코드


주석에서는 공장, 마트를 통해 비유를 해 두었다.


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
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
 
sem_t produce, consume;
int storagebox; // 아이템 보관함(1개만 저장 가능)
 
void *producerRoutine(void *argumentPointer)
{
    int i, item;
    for(i = 0; i < 10000; i ++)
    {
        item = i;
        
        // 하나 생산했으니 다른 곳에서
        // storagebox를 접근하지 못하도록 한다. (생산 공장 문을 닫는다.)
        sem_wait(&produce);
        
        // storagebox에 아이템(i)를 넣어준다.
        // 단 하나의 제품만 슈퍼마켓에 넣어준다.
        printf("Producer message :: Give item to storagebox :: %d\n",item);
        storagebox = i;
 
        // 그 후 소비하는 곳에서
        // 아이템을 가져갈 수 있도록 V를 해준다.(슈퍼마켓 문을 연다.)
        sem_post(&consume);
    }
 
    return NULL;
}
 
void *consumerRoutine(void *argumentPointer)
{
    int i, item;
    for(i = 0; i < 10000; i ++)
    {
        // 아이템 하나를 받아오기 위해
        // 다른 곳에서 storagebox를 접근하지 못하도록 한다.(슈퍼마켓 문을 닫는다.)
        sem_wait(&consume);
        
        // consumer item변수에 storagebox에 있던
        // 아이템을 넣어준다. (한명만 물건을 사도록 한다.)
        item = storagebox;
        printf("Consumer message :: Take item from storagebox :: %d\n",item);
        // 다시 생산 할 수 있도록 V를 해준다. (생산 공장 문을 연다.)
        sem_post(&produce);
    }
 
    return NULL;
}
 
int main()
{
    pthread_t producerID, consumerID;
 
    // 처음에는 생산을 해야되고 소비할 것이 없으니 각각 1,0으로 초기화한다.
    sem_init(&produce, 01);
    sem_init(&consume, 00);
 
    pthread_create(&producerID, NULL, producerRoutine, NULL);
    pthread_create(&consumerID, NULL, consumerRoutine, NULL);
 
    // 스레드 조인
    pthread_join(producerID, NULL);
    pthread_join(consumerID, NULL);
 
    printf("Finish Producer and Consumer !! \n");
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus



데드락이 일어나는지 다음 동영상을 통해 확인해 보고,


프로듀서 컨슈머가 어떻게 작동하는지 이해해 보자.











반응형