Monday, June 2, 2008

Thread, mutex - deadlock/race condition avoidance

여러개의 thread가 같은 메모리에 접근할 때 발생할 수 있는 문제가 deadlock, race condition이다. deadlock을 만드는 가장 간단한 방법은 같은 mutex에 두번 lock을 거는 것이다. 혹은 두 thread A,B가 있고 mutex X,Y가 있을 때 A가 X를 lock하고 Y자원을 사용하고자 기다릴때 B가 Y를 lock하고 X자원을 사용하고자하는 경우 이런 상황이 발생한다. thread에서 이런 상황을 피하는 방법으로는 아래의 두가지가 있다.

  • 여러 mutex를 사용하는 경우 lock하는 순서를 항상 동일하게 한다. (위의 예라면 항상 X를 lock한 후 Y를 lock하는 식으로 정해서 deadlock을 피할 수 있다)

  • 자신이 사용하고자 하는 자원이 다른 thread에 의해 사용중인 경우 자신이 점유하고 있는 자원을 해제한 후 기다린다.


linux에서 사용가능한 mutex관련 함수로는 아래 것들이 있다.

#include <pthread.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);

mutex를 사용하기 위해서는 ..._init(), ..._destroy() 함수들을 사용해야한다. ..._init()함수 사용시 mutex의 종류를 정해줄 수 있는데, 아래와 같은 매크로로 지정할 수 있다.

  • PTHREAD_MUTEX_NORMAL : linux에서는 "timed" mutex이다.

  • PTHREAD_MUTEX_RECURSIVE : 여러번 잠글 수 있는 mutex

  • PTHREAD_MUTEX_ERRORCHECK : 에러 체크해주는 mutex

  • PTHREAD_MUTEX_MUTEX_DEFAULT : linux에서는 첫번째의 ..._NORMAL과 같다.


위에서 설명한 "timed mutex"는 기본 mutex인데, 중복으로 lock을 걸면 deadlock에 걸리고, 다른 thread가 lock한 상태에서 내가 풀려고 하면 undefined 상태가 된다. errorcheck 타입은 데드락의 경우 에러를 리턴해준다. 그 외에 adaptive mutex가 있는데, 표준은 아니고, 플랫폼에 따라 최적의 매커니즘으로 동작하게 된다. linux에서 SMP가 지원되는 경우 spinlock을 사용하게 되는데, 이때 adaptive mutex를 사용하게 되면 짧은 시간동안의 lock, unlock에 대해 최적의 성능을 지원한다. 대신 비 표준이라 PTHREAD_MUTEX_ADAPTIVE_NP를 통해 초기화 한다.

이런 mutex 타입을 mutex attribute 함수들을 통해 설정하여 mutex init시 사용하면 된다.

#include <pthread.h>
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutex_gettype(pthread_mutexattr_t *restrict attr);
int pthread_mutex_settype(pthread_mutexattr_t *attr, int type);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

No comments:

Post a Comment