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(임계영역)문제인데, 이와 관련해서는 이 전의 포스팅을 참조하기 바란다.

http://taesun1114.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B0%84-%ED%86%B5%EC%8B%A0%EA%B3%B5%EC%9C%A0%EB%A9%94%EB%AA%A8%EB%A6%AC

따라서, 각각의 쓰레드가 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

+ Recent posts