Mutex는 스레드 동기화를 구현하고 여러 쓰기가 발생할 때 공유 데이터를 보호하는 주요 수단
- 공유 데이터 리소스에 대한 액세스를 보호하는 잠금 역할
- 한 번에 하나의 스레드만 mutex 변수를 잠그거나 소유할 수 있다.
- 따라서 여러 스레드가 mutex를 잠그려고 해도 하나의 스레드만 성공
- 소유한 스레드가 해당 mutex를 잠금 해제할 때까지 다른 스레드는 해당 mutex 소유 불가능
- 스레드는 보호된 데이터에 번갈아가며 액세스해야
- Mutex는 race condition을 방지하는 데 사용
Mutex 소유 → 전역 변수 업데이트
- 업데이트되는 변수 → critical section에 속함
Mutex를 사용하는 것은 프로그래머의 책임!
Mutex 실행 순서
- Mutex 변수 생성 후 초기화
- 여러 스레드가 mutex를 잠그려 시도
- 하지만 하나만 성공하며 해당 스레드가 mutex 소유
- 소유한 스레드가 동작 수행
- 소유한 스레드가 mutex 잠금 해제
- 다른 스레드가 mutex 획득 과정 반복
- mutex 파괴
Mutex 생성
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t
- Mutex lock을 표현하는 변수 형식
- 사용 전에 반드시 초기화되어야 함
정적 변수의 초기화
- 단순히 'PTHREAD_MUTEX_INITIALIZER'를 할당하면 된다.
- 동적으로 할당된 변수의 초기화
pthread_mutex_init() 함수 호출
- mutex 속성 객체를 위한 'attr' 매개변수, 기본값은 NULL
- 성공 시 0, 실패 시 0이 아닌 오류 코드 return
이미 초기화된 mutex의 초기화 → 동작이 정의되어 있지 않음
Mutex Destroy(파괴)
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex)
성공 시 0, 실패 시 0이 아닌 오류 코드 return
스레드가 파괴된 후에 mutex를 참조하는 경우
하나의 스레드가 파괴 함수를 호출하고 다른 스레드가 mutex를 잠근 경우
→ 정의되지 않은 동작
Mutex Locking/unlocking
#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)
pthread_mutex_lock()
- Mutex가 사용 가능할 때까지 블록됨
pthread_mutex_trylock()
- 항상 즉시 반환됨
- 성공 시 0, 실패 시 0이 아닌 오류 코드 return
예시
pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mylock);
/* critical section */
pthread_mutex_unlock(&mylock);
At-Most-Once execution
#include <pthread.h>
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
pthread_once_t once_control = PTHREAD_ONCE_INIT;
mutex에 액세스하기 전에 pthread_mutex_init을 호출하는 것이 중요
→ 하지만 mutex를 초기화하는 작업은 모든 스레드에 대해 정확하게 한 번만 이루어져야 하며 각 스레드가 독자적으로 초기화하면 문제가 발생할 수 있다!
pthread_once()
- 'once_control'은 PTHREAD_ONCE_INIT으로 정적으로 초기화되어야 함
- 'init_routine'은 **pthread_once**가 처음 호출될 때 호출되며 이후의 호출에서는 호출되지 않음
At-least-once semantics are important for initialization
- If you choose to use pthread_mutex_init, you need both atmost-once and at-least-once semantics (= exactly once)
- -> At-Most-Once도 중요하지만 At-Least-Once도 중요하다!
'Study > 시스템프로그래밍' 카테고리의 다른 글
[시스템프로그래밍] 임계구역과 세마포어에 관하여 (1) | 2023.12.05 |
---|---|
[시스템프로그래밍] 조건 변수와 시그널, Reader-Writer problem에 관하여 (1) | 2023.12.05 |
[시스템프로그래밍] 스레드 (0) | 2023.12.04 |
[시스템프로그래밍] 시간과 타이머 (0) | 2023.12.03 |
[시스템프로그래밍] Signals (1) | 2023.12.03 |