공동구역?
int a = 2; while(1) {} |
int b = 3; while(1) {} |
int c = 4; while(1) {} |
쓰레드1 |
쓰레드2 |
쓰레드3 |
프로세스(공유 자원) |
Critical Area
1 2 3 4 5 6 | bool flag[2] // 불린 배열(Boolean array) int turn // 정수형 변수 flag[0] = false // false은 임계 구역 사용을 원하지 않음을 뜻함. flag[1] = true turn = 0 // 0 은 0번 프로세스를 가리킴, 1은 1번 프로세스를 가리킴 | cs |
○ Process (0)
1 2 3 4 5 6 7 8 9 10 11 | flag[0] = true // 임계 구역 사용을 원함 turn = 1 // 1번 프로세스에게 차례가 감 while( flag[1] && turn == 1 ) { // flag[1] 이 turn[1] 을 가지고 있으므로 //현재 사용중임 // 임계 구역이 사용 가능한지 계속 확인 }// 임계 구역 ... // 임계 구역의 끝 flag[0] = false | cs |
○ Process ①
1 2 3 4 5 6 7 8 9 | flag[1] = true turn = 0 while( flag[0] && turn == 0 ) { // 임계 구역이 사용 가능한지 계속 확인 }// 임계 구역 ... // 임계 구역의 끝 flag[1] = false | cs |
우리는 기본적인 동기화에 대한 중요성을 알았으니 다음은 방법을 알아보자.
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 35 36 37 38 39 | #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> // 뮤텍스 객체 선언 pthread_mutex_t mutex_lock; int g_count = 0; // 쓰레드 공유자원. void *t_function(void *data) { int i; char* thread_name = (char*)data; pthread_mutex_lock(&mutex_lock); // critical section for (i = 0; i < 3; i++) { printf("%s COUNT %d\n", thread_name, g_count); g_count++; // 쓰레드 공유자원 sleep(1); } pthread_mutex_unlock(&mutex_lock); } int main() { pthread_t p_thread1, p_thread2; int status; // 뮤텍스 객체 초기화, 기본 특성으로 초기화 했음 pthread_mutex_init(&mutex_lock, NULL); pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1"); pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2"); pthread_join(p_thread1, (void *)&status); pthread_join(p_thread2, (void *)&status); } |
# compile :: gcc -o name name.c -lpthread
[ 실행 결과 ]
Thread2 COUNT0
Thread2 COUNT1
Thread2 COUNT2
Thread1 COUNT3
Thread1 COUNT4
Thread1 COUNT5
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 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #include <semaphore.h> #include <pthread.h> #include <stdio.h> sem_t semaphore; int num = 2; void *threadF1(void *arg) { int i; if(num != 0) { num--; sem_wait(&semaphore); printf("스레드 1이 화장실을 이용하기 시작합니다.\n"); // 화장실 이용하는 시간이라 가정 for(i = 0 ; i < 1000000 ; i++){} num++; sem_post(&semaphore); printf("스레드 1이 화장실 이용을 마쳤습니다.\n"); } else if(num == 0) { printf("화장실이 꽉 차 스레드 1이 기다리고 있습니다.\n"); while(num == 0){} num++; sem_post(&semaphore); printf("스레드 1이 화장실 이용을 하고 마쳤습니다.\n"); } return NULL; } void *threadF2(void *arg) { int i; if(num != 0) { num--; sem_wait(&semaphore); printf("스레드 2가 화장실을 이용하기 시작합니다.\n"); // 화장실 이용하는 시간이라 가정 for(i = 0 ; i < 1000000 ; i++){} num++; sem_post(&semaphore); printf("스레드 2가 화장실 이용을 마쳤습니다.\n"); } else if(num == 0) { printf("화장실이 꽉 차 스레드 2가 기다리고 있습니다.\n"); while(num == 0){} num++; sem_post(&semaphore); printf("스레드 2가 화장실 이용을 하고 마쳤습니다.\n"); } return NULL; } void *threadF3(void *arg) { int i; if(num != 0) { num--; sem_wait(&semaphore); printf("스레드 3이 화장실을 이용하기 시작합니다.\n"); // 화장실 이용하는 시간이라 가정 for(i = 0 ; i < 1000000 ; i++){} num++; sem_post(&semaphore); printf("스레드 3이 화장실 이용을 마쳤습니다.\n"); } else if(num == 0) { printf("화장실이 꽉 차 스레드 3이 기다리고 있습니다.\n"); while(num == 0){} num++; sem_post(&semaphore); printf("스레드 3이 화장실 이용을 하고 마쳤습니다.\n"); } return NULL; } int main() { pthread_t thread1, thread2, thread3; sem_init(&semaphore, 0, 2); // return :: 0 -> success , others -> fail printf("Semaphore test Start!\n"); // 스레드 생성 pthread_create(&thread1, NULL, threadF1, NULL); pthread_create(&thread2, NULL, threadF2, NULL); pthread_create(&thread3, NULL, threadF3, NULL); // 스레드 조인 pthread_join(thread1, NULL); pthread_join(thread2, NULL); pthread_join(thread3, NULL); printf("모든 스레드가 화장실 이용을 끝냈습니다.\n"); // 세마포어 객체 소멸 sem_destroy(&semaphore); return 0; } | cs |
1. 순조롭게 화장실을 왔다 갔다 하는 모습이다.
2. 화장실이 2개밖에 없으므로 모두 사용시 스레드 1이 블록되는 모습을 볼 수 있다.
세마포와 뮤텍스의 차이?
'Developer > OS' 카테고리의 다른 글
7. Virtual Memory - 가상메모리 (1) | 2018.12.20 |
---|---|
6. Memory Fragmentation - 메모리 단편화 (0) | 2018.12.18 |
5. Monitor & Deadlock - 모니터, 데드락 (0) | 2018.12.17 |
2. Process - 프로세스 (0) | 2018.12.11 |
1. What is Operation System? 운영체제란? (0) | 2018.12.11 |
공동구역?
int a = 2; while(1) {} |
int b = 3; while(1) {} |
int c = 4; while(1) {} |
쓰레드1 |
쓰레드2 |
쓰레드3 |
프로세스(공유 자원) |
Critical Area
1 2 3 4 5 6 | bool flag[2] // 불린 배열(Boolean array) int turn // 정수형 변수 flag[0] = false // false은 임계 구역 사용을 원하지 않음을 뜻함. flag[1] = true turn = 0 // 0 은 0번 프로세스를 가리킴, 1은 1번 프로세스를 가리킴 | cs |
○ Process (0)
1 2 3 4 5 6 7 8 9 10 11 | flag[0] = true // 임계 구역 사용을 원함 turn = 1 // 1번 프로세스에게 차례가 감 while( flag[1] && turn == 1 ) { // flag[1] 이 turn[1] 을 가지고 있으므로 //현재 사용중임 // 임계 구역이 사용 가능한지 계속 확인 }// 임계 구역 ... // 임계 구역의 끝 flag[0] = false | cs |
○ Process ①
1 2 3 4 5 6 7 8 9 | flag[1] = true turn = 0 while( flag[0] && turn == 0 ) { // 임계 구역이 사용 가능한지 계속 확인 }// 임계 구역 ... // 임계 구역의 끝 flag[1] = false | cs |
우리는 기본적인 동기화에 대한 중요성을 알았으니 다음은 방법을 알아보자.
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 35 36 37 38 39 | #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> // 뮤텍스 객체 선언 pthread_mutex_t mutex_lock; int g_count = 0; // 쓰레드 공유자원. void *t_function(void *data) { int i; char* thread_name = (char*)data; pthread_mutex_lock(&mutex_lock); // critical section for (i = 0; i < 3; i++) { printf("%s COUNT %d\n", thread_name, g_count); g_count++; // 쓰레드 공유자원 sleep(1); } pthread_mutex_unlock(&mutex_lock); } int main() { pthread_t p_thread1, p_thread2; int status; // 뮤텍스 객체 초기화, 기본 특성으로 초기화 했음 pthread_mutex_init(&mutex_lock, NULL); pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1"); pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2"); pthread_join(p_thread1, (void *)&status); pthread_join(p_thread2, (void *)&status); } |
# compile :: gcc -o name name.c -lpthread
[ 실행 결과 ]
Thread2 COUNT0
Thread2 COUNT1
Thread2 COUNT2
Thread1 COUNT3
Thread1 COUNT4
Thread1 COUNT5
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 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #include <semaphore.h> #include <pthread.h> #include <stdio.h> sem_t semaphore; int num = 2; void *threadF1(void *arg) { int i; if(num != 0) { num--; sem_wait(&semaphore); printf("스레드 1이 화장실을 이용하기 시작합니다.\n"); // 화장실 이용하는 시간이라 가정 for(i = 0 ; i < 1000000 ; i++){} num++; sem_post(&semaphore); printf("스레드 1이 화장실 이용을 마쳤습니다.\n"); } else if(num == 0) { printf("화장실이 꽉 차 스레드 1이 기다리고 있습니다.\n"); while(num == 0){} num++; sem_post(&semaphore); printf("스레드 1이 화장실 이용을 하고 마쳤습니다.\n"); } return NULL; } void *threadF2(void *arg) { int i; if(num != 0) { num--; sem_wait(&semaphore); printf("스레드 2가 화장실을 이용하기 시작합니다.\n"); // 화장실 이용하는 시간이라 가정 for(i = 0 ; i < 1000000 ; i++){} num++; sem_post(&semaphore); printf("스레드 2가 화장실 이용을 마쳤습니다.\n"); } else if(num == 0) { printf("화장실이 꽉 차 스레드 2가 기다리고 있습니다.\n"); while(num == 0){} num++; sem_post(&semaphore); printf("스레드 2가 화장실 이용을 하고 마쳤습니다.\n"); } return NULL; } void *threadF3(void *arg) { int i; if(num != 0) { num--; sem_wait(&semaphore); printf("스레드 3이 화장실을 이용하기 시작합니다.\n"); // 화장실 이용하는 시간이라 가정 for(i = 0 ; i < 1000000 ; i++){} num++; sem_post(&semaphore); printf("스레드 3이 화장실 이용을 마쳤습니다.\n"); } else if(num == 0) { printf("화장실이 꽉 차 스레드 3이 기다리고 있습니다.\n"); while(num == 0){} num++; sem_post(&semaphore); printf("스레드 3이 화장실 이용을 하고 마쳤습니다.\n"); } return NULL; } int main() { pthread_t thread1, thread2, thread3; sem_init(&semaphore, 0, 2); // return :: 0 -> success , others -> fail printf("Semaphore test Start!\n"); // 스레드 생성 pthread_create(&thread1, NULL, threadF1, NULL); pthread_create(&thread2, NULL, threadF2, NULL); pthread_create(&thread3, NULL, threadF3, NULL); // 스레드 조인 pthread_join(thread1, NULL); pthread_join(thread2, NULL); pthread_join(thread3, NULL); printf("모든 스레드가 화장실 이용을 끝냈습니다.\n"); // 세마포어 객체 소멸 sem_destroy(&semaphore); return 0; } | cs |
1. 순조롭게 화장실을 왔다 갔다 하는 모습이다.
2. 화장실이 2개밖에 없으므로 모두 사용시 스레드 1이 블록되는 모습을 볼 수 있다.
세마포와 뮤텍스의 차이?
'Developer > OS' 카테고리의 다른 글
7. Virtual Memory - 가상메모리 (1) | 2018.12.20 |
---|---|
6. Memory Fragmentation - 메모리 단편화 (0) | 2018.12.18 |
5. Monitor & Deadlock - 모니터, 데드락 (0) | 2018.12.17 |
2. Process - 프로세스 (0) | 2018.12.11 |
1. What is Operation System? 운영체제란? (0) | 2018.12.11 |