Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>
Docbook 원문

pthread_mutex_lock(3)

1장. pthread_mutex_lock(3)

차례
1.1절. 사용법
1.2절. 설명
1.3절. 반환값
1.4절. 에러
1.5절. 예제
1.6절. 참고문헌

뮤텍스 잠금을 얻거나 해제한다.


1.1절. 사용법

#include <pthrad.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
		


1.2절. 설명

mutex는 MUTual EXclusion(상호 배제)devide의 줄임말로 쓰레드간 공유하는 데이터 영역을 보호하기 위해서 사용한다. 데이터 영역의 보호는 critical section(임계 영역)을 만들고 임계 영역내에 단하나의 쓰레드만이 진입가능 하도록 하는 방식을 사용한다.

보통 이 임계영역에는 보호하고자 하는 데이터에 대한 접근/수정 루틴이 들어간다. 데이터에 대한 접근/수정 루틴에 오직 하나의 쓰레드만 접근 가능하게 되므로 결국 데이터를 보호할 수 있게 된다.

뮤텍스는 단지 2개의 가능한 행동만이 정의되어 있다. unlock와 lock이 그건데, lock는 임계영역은 진입하기 위한 요청, unlock는 임계영역을 빠져나오면서 다른 쓰레드에게 임계영역을 되돌려주기 위해서 사용한다. 만약 쓰레드가 임계영역이 진입하기 위해서 lock를 시도 했는데, 다른 쓰레드가 이미 임계영역에 진입했다면 해당 쓰레드가 unlock를 해서 임계영역을 빠져나오기 전까지 기다리게 된다.

mutex는 fastrecursive의 2가지 종류가 지원된다. 이것은 lock을 얻은 쓰레드가 다시 lock를 얻을 수 있도록 할 것인지를 결정하기 위해서 사용한다. 기본적으로 mutex의 종류는 fast 상태로 시작된다. mutex 종류에 대한 자세한 내용은 pthread_mutexattr_init(3)을 참고하기 바란다.

pthread_mutex_t는 뮤텍스의 특징을 결정하기 위해서 사용한다. PTHREAD_MUTEX_INITIALIZER(fast mutex)와 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP(recursive mutexe), PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP(mutx 에러 체크용)의 3가지 상수가 준비되어 있다. 이중 하나를 선택하면 된다.

pthread_mutex_lock()는 (임계영역에 진입하기 위함)뮤텍스 잠금을 요청한다. 만약 뮤텍스의 최근 상태가 unlocked라면 쓰레드는 잠금을 얻고 임계영역에 진입하게 되고 리턴한다. 다른 쓰레드가 뮤텍스 잠금을 얻은 상태라면 잠금을 얻을 수 있을 때까지 기다리게 된다.

pthread_mutex_unlock()는 뮤텍스잠금을 되돌려준다. 만약 fast 뮤텍스라면 pthread_mutex_unlock()는 언제나 unlocked 상태를 되돌려준다. recursive 뮤텍스라면 잠겨있는 뮤텍스의 수를 감소시키고 이 수가 0이 된다면 뮤텍스잠금을 되돌려주게 된다.

pthread_mutex_destory()는 뮤텍스 객체를 삭제하고 자원을 되돌려준다. 더이상 사용하지 않는 뮤텍스는 반드시 이 함수를 이용해서 삭제하도록 하자. 리눅스에서 쓰레드는 뮤텍스 객체와 별개로 되어 있다. 그러므로 쓰레드가 종료되었다고 하더라도 뮤텍스 객체는 여전히 남아 있게 된다. 이 함수를 호출해야지만 뮤텍스 객체가 삭제 된다.


1.3절. 반환값

pthread_mutex_init()는 언제나 0을 리턴한다. 다른 뮤텍스 함수들은 성공했다면 0, 실패했다면 0이 아닌 수를 리턴하고 errno를 설정한다.


1.4절. 에러

pthread_mutex_lock()함수는 아래의 에러코드를 반환한다.

EINVAL

뮤텍스가 잘못 초기화 되었다.

EDEADLK

이미 잠금을 얻은 쓰레드가 다시 잠금을 요청할 때 (error checking 뮤텍스일 경우 사용할 수 있다)

pthread_mutex_trylock()함수는 아래의 에러코드를 반환한다.

EBUSY

뮤텍스가 잠겨 있어서 잠금을 얻을 수 없다.

EINVAL

뮤텍스가 잘못 초기화 되었다.


1.5절. 예제

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>

using namespace std;

void *ping(void *);
void *pong(void *);

pthread_mutex_t sync_mutex;
pthread_cond_t  sync_cond;

pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  gcond  = PTHREAD_COND_INITIALIZER;

int main()
{
    vector<void *(*)(void *)> thread_list;
    vector<pthread_t> tident(10); 
    int thresult;
    int status;
    int i;

    pthread_mutex_init(&sync_mutex, NULL);
    pthread_cond_init(&sync_cond, NULL);

    thread_list.push_back(pong);
    thread_list.push_back(ping);

    for(i = 0; i < thread_list.size(); i++ )
    {
        pthread_mutex_lock(&ync_mutex);
        if (pthread_create(&tident[i], NULL, thread_list[i], (void *)NULL) <0)
        {
            perror("error:");
            exit(0);
        }
        pthread_cond_wait(&sync_cond, &sync_mutex);
        pthread_mutex_unlock(&sync_mutex);
    }
    for (i = 0; i < tident.size(); i++)
    {
        pthread_join(tident[i], (void **)&status);
    }
}

void *ping(void *data)
{
    int i=0;
    pthread_mutex_lock(&sync_mutex);
    pthread_cond_signal(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
    while(1)
    {
        pthread_mutex_lock(&gmutex);
        printf("%d : ping\n", i);
        pthread_cond_signal(&gcond);
        pthread_cond_wait(&gcond, &gmutex);
        pthread_mutex_unlock(&gmutex);
        usleep(random()%100);
        i++;
    }
}

void *pong(void *data)
{
    int i = 0;
    pthread_mutex_lock(&sync_mutex);
    sleep(1);
    pthread_cond_signal(&sync_cond);
    pthread_mutex_unlock(&sync_mutex);
    while(1)
    {
        pthread_mutex_lock(&gmutex);
        pthread_cond_wait(&gcond, &gmutex);
        printf("%d : pong\n", i);
        pthread_cond_signal(&gcond);
        pthread_mutex_unlock(&gmutex);
        i++;
    }
}