Post

[운영체제/구현] Mutex, Spinlock, Semaphore 구현

1. Mutex 구현

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
#include <stdio.h>
#include <pthread.h>

int sum = 0;
pthread_mutex_t lock;

void * worker(void * arg){
    printf("%s 시작\t %d\n", (char*)arg, sum);
    for(int i = 0 ; i < 1000000 ; i ++){
        pthread_mutex_lock(&lock);
        sum += 10;
        pthread_mutex_unlock(&lock);
    }
    printf("%s 끝\t %d\n", (char*)arg, sum);
}

int main(){
    char * name[] = {"황기태", "이찬수"};
    pthread_t pid[2];
    pthread_attr_t attr[2];

    for(int i = 0 ; i < 2 ; i ++)
        pthread_attr_init(&attr[i]);
    
    pthread_mutex_init(&lock, NULL);
    for(int i = 0 ; i < 2 ; i ++)
        pthread_create(&pid[i], &attr[i], worker, name[i]);
    
    for(int i = 0 ; i < 2 ; i ++)
        pthread_join(pid[i], NULL);
    printf("최종 sum = %d\n", sum);
    pthread_mutex_destroy(&lock);
    return 0;
}

2. Spinlock 구현

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
#include <stdio.h>
#include <pthread.h>

int sum = 0;
pthread_spinlock_t lock;

void * worker(void * arg){
    printf("%s 시작\t %d\n", (char*)arg, sum);
    for(int i = 0 ; i < 1000000 ; i ++){
        pthread_spin_lock(&lock);
        sum += 10;
        pthread_spin_unlock(&lock);
    }
    printf("%s 끝\t %d\n", (char*)arg, sum);
}

int main(){
    char * name [] = {"황기태","이찬수"};
    pthread_t pid[2];
    pthread_attr_t attr[2];
    
    
    for(int i = 0 ; i < 2 ; i++)
    	pthread_attr_init(&attr[i]);
    
    pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
    
    for(int i = 0 ; i < 2 ; i++)
        pthread_create(&pid[i], &attr[i], worker, name[i]);
    
    for(int i = 0 ; i < 2 ; i++)
        pthread_join(pid[i],NULL);
    printf("최종 sum = %d\n", sum);
    pthread_spin_destroy(&lock);
    
    return 0;
}

3. Semaphore

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
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

sem_t toiletsem;

void * guestThread(void * arg){
    int cnt = -1;
    
    sem_wait(&toiletsem);
    sem_getvalue(&toiletsem, &cnt);
    printf("고객%s 화장실에 들어간다... 세마포 counter %d\n", (char*)arg, cnt);
    sleep(1);
    printf("고객%s 화장실에서 나온다.\n", (char*)arg);
    sem_post(&toiletsem);
}

#define NO 0
#define MAX_COUNTER 3

int main(){
    int counter = -1;
    char * name [] = {"1","2","3","4","5"};
    pthread_t pid[5];
    
    int res = sem_init(&toiletsem, NO, MAX_COUNTER);
    if (res == -1){
        printf("semaphore is not supported\n");
        return 0;
    }
    sem_getvalue(&toiletsem, &counter);
    printf("세마포 counter = %d\n", counter);
    
    for(int i = 0 ; i < 5 ; i ++)
        pthread_create(&pid[i], NULL, guestThread, name[i]);
    
    for(int i = 0 ; i < 5 ; i ++)
        pthread_join(pid[i], NULL);
    
    printf("세마포 counter = %d\n", counter);
    sem_destroy(&toiletsem);
    
    return 0;
}

4. 생산자 소비자 문제

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
81
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>

#define MILLI 1000
#define N_COUNTER 4

void mywrite(int n);
int myread();

pthread_mutex_t critical_section;
sem_t semWrite, semRead;
int queue[N_COUNTER];
int wIdx = 0;
int rIdx = 0;

void * producer(void * arg){
    for(int i = 0 ; i < 10 ; i ++){
        mywrite(i);
        int m = rand() % 10;
        usleep(MILLI * m * 10);
    }
    return NULL;
}

void * consumer(void * arg){
    for(int i = 0 ; i < 10 ; i ++){
        int n = myread();
        int m = rand() % 10;
        usleep(MILLI * m * 10);
    }
    return NULL;
}

void mywrite(int n){
	sem_wait(&semWrite); // 잔여 버퍼 용량 -1
    pthread_mutex_lock(&critical_section);
    queue[wIdx] = n;
    wIdx = (wIdx + 1) % N_COUNTER;
    pthread_mutex_unlock(&critical_section);
    printf("producer : wrote %d\n", n);
    sem_post(&semRead); // 현재 버퍼 용량 + 1
}

int myread(){
    sem_wait(&semRead); // 현재 버퍼 용량 - 1
    pthread_mutex_lock(&critical_section);
    int n = queue[rIdx];
    rIdx = (rIdx + 1) % N_COUNTER;
    pthread_mutex_unlock(&critical_section);
    printf("consumer : read %d\n", n);
    sem_post(&semWrite); // 잔여 버퍼 용량 + 1 
    return n;
}

int main(){
    pthread_t pid[2];
    
    srand(time(NULL));
    pthread_mutex_init(&critical_section, NULL);
    int res = sem_init(&semWrite, 0, N_COUNTER);
    if (res == -1){
        printf("semaphore is not supported\n");
        return 0;
    }
    sem_init(&semRead, 0, 0);
    
    pthread_create(&pid[0], NULL, producer, NULL);
    pthread_create(&pid[1], NULL, consumer, NULL);
    
    for(int i = 0 ; i < 2 ; i ++)
        pthread_join(pid[i], NULL);
    
    sem_destroy(&semWrite);
    sem_destroy(&semRead);
    
    pthread_mutex_destroy(&critical_section);
    return 0;
}
This post is licensed under CC BY 4.0 by the author.