Mutex란?
Mutual Exclustion의 으로, Critical Section문제를 해결하기 위한 방법중 하나이다.
뮤텍스 개체는 잠겨지지 않은(unlocked)상태와 잠금(locked)상태의 두가지 상태를 가지며, 동시에 둘 이상의 쓰레드가 소유할 수 없다. 뮤텍스는 잠그기 위해 기다리는 쓰레드들을 위한 큐를 가지고 있어서, 이미 다른 쓰레드에 의해 잠겨 있는 뮤텍스를 획득하려고 시도하면 쓰레드는 큐에 들어가고 다시 대기상태로 빠지게 된다.
Mutex 생성,소멸 함수.
#include<pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *addr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex -> 뮤텍스 생성시에는 뮤텍스의 참조 값 저장을 위한 변수의 주소 값 전달, 그리고 뮤텍스
소멸 시에는 소멸하고자 하는 뮤텍스의 참조 값을 저장하고 있는 변수의 주소값 전달.
attr -> 생성하는 뮤텍스의 특성정보를 담고 있는 변수의 주소 값 전달. 별도의 특성을 지정하지 않을
경우 NULL 전달.
Mutex lock,unlock 함수
#include<pthread.h>
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_unlock(pthread_mutex *mutex);
예제)
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#define NUM_THREAD 100
void *thread_inc(void *arg);
void *thread_des(void *arg);
long long num =0;
int main(int argc,char *argv[]){
pthread_t thread_id[NUM_THREAD]; //Thread ID를 저장할 배열.
int i;
printf("sizeof long long : %d\n",sizeof(long long));
for(i=0;i<NUM_THREAD;i++){
if(i%2)
pthread_create(&(thread_id[i]),NULL,thread_inc,NULL);
//thread를 생성하고, 생성된 thread는 thread_inc를 실행한다.
else
pthread_create(&(thread_id[i]),NULL,thread_des,NULL);
//thread를 생성하고, 생성된 thread는 thread_des를 실행한다.
}
for(i=0;i<NUM_THREAD;i++)
pthread_join(thread_id[i],NULL); //각각의 thread가 끝날때까지 주프로세스가기다림.
printf("result : %lld \n",num);
return 0;
}
void *thread_inc(void *arg){ //짝수 thread가 실행하는 부분.
int i;
for(i=0;i<50000000;i++)
num+=1;
}
void *thread_des(void *arg){ //홀수 thread가 실행하는 부분.
int i;
for(i=0;i<50000000;i++)
num-=1;
}
<출처 : 윤성우 열혈 TCP/IP 소켓프로그래밍>
위와 같은 소스를 가지고 있는 프로그램이 있다. 쓰레드를 100개 생성시키고, 50개는 num을 증가시키고 나머지 50개는 num을 감소시키는 프로그램이다. 이 프로그램을 실행시키면 원하는 답은 0이지만 실행 결과는 그렇지 않다.
위와 같은 일이 발생하는 이유는 Critical Section(임계영역)문제인데, 이와 관련해서는 이 전의 포스팅을 참조하기 바란다.
따라서, 각각의 쓰레드가 num+=1 or num-=1을 실행할 때는 다른 쓰레드가 이 부분에 접근하면 안된다. 이를 위해서 Mutex를 사용한다.
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#define NUM_THREAD 100
void *thread_inc(void *arg);
void *thread_des(void *arg);
long long num =0;
int main(int argc,char *argv[]){
pthread_t thread_id[NUM_THREAD]; //Thread ID를 저장할 배열.
int i;
pthread_mutex_init(&mutex,NULL); // mutex생성함수.
printf("sizeof long long : %d\n",sizeof(long long));
for(i=0;i<NUM_THREAD;i++){
if(i%2)
pthread_create(&(thread_id[i]),NULL,thread_inc,NULL);
//Thread를 생성하고 thread_inc를 실행한다.
else
pthread_create(&(thread_id[i]),NULL,thread_des,NULL);
//Thread를 생성하고 thread_des를 실행한다.
}
for(i=0;i<NUM_THREAD;i++)
pthread_join(thread_id[i],NULL); //각각의 thread가 끝날때까지 기다림.
printf("result : %lld \n",num);
pthread_mutex_destroy(&mutex); //Mutex소멸함수.
return 0;
}
void *thread_inc(void *arg){
int i;
pthread_mutex_lock(&mutex); //Mutex를 이용,다른쓰레드의 접근을 막는다.
for(i=0;i<50000000;i++)
num+=1;
pthread_mutex_unlock(&mutex); //Critical section을 벗어났으므로, 다른쓰레드 접근허용.
}
void *thread_des(void *arg){
int i;
pthread_mutex_lock(&mutex); //다른 쓰레드의 접근을 막는다.
for(i=0;i<50000000;i++)
num-=1;
pthread_mutex_unlock(&mutex); //Critical section을 벗어났으므로, 다른쓰레드 접근허용.
}
'O.S' 카테고리의 다른 글
IDT / LDT / GDT / SSDT (1) | 2012.09.26 |
---|---|
Flag Register (0) | 2012.07.20 |
Classic Problems of Synchronization / Monitor (0) | 2012.04.27 |
Synchronization Hardware (0) | 2012.04.27 |
Semaphore (0) | 2012.04.27 |