
뮤텍스(Mutex)란?
: 뮤텍스(Mutex)는 Mutual Exclusion의 줄임말로, 다중 스레드 환경에서 공유 자원에 대한 동시 접근을 방지하기 위한
동기화 매커니즘이다. 뮤텍스를 사용하면 여러 스레드가 동시에 공유 자원에 접근하지 못하게 해
데이터 경합이나 데이터 불일치 문제를 방지할 수 있다.
뮤텍스의 필요성
: 프로그램에서 여러 스레드가 동시에 실행되면서, 공유 자원을 동시 접근하는 상황이 발생할 수 있다.
예를 들어, 여러 스레드가 동시에 하나의 변수에 접근하여 값을 변경하려고 할 때,
한 스레드가 작업을 완료하기 전에 다른 스레드가 그 변수에 접근하면 정확하지 않은 값이 나올 수 있다.
이를 방지하기 위해, 특정 스레드가 자원에 접근할 때 다른 스레드는 그 자원이 잠겨 있다는 것을 알 수 있도록 하는 장치가 필요한데, 뮤텍스는 이 역할을 수행하는 잠금장치로 이용된다. (따라서 Mutex를 Lock 이라고도 한다.)
뮤텍스에 대해서 비유적으로 설명한 글을 인용하자면, 화장실이 하나 뿐인 식당과 같다.

1. 화장실이라는 공유자원을 이용하기 위해 한 사람이 접근하고

2. 그 사람이 쓰는 동안은 공유자원이 문(MUTEX)에 의해 LOCK되어 이용하지 못한다.

3. 공유자원을 사용하고 난 후, 그 다음 대기열에 있던 사람이 이용하기 위해 접근한다.
뮤텍스의 동작원리
1. 잠금 (Lock)
: 위에서 언급 했던 것처럼 어떤 스레드가 공유 자원에 접근하려고 하면, 뮤텍스를 잠궈 그 자원을 사용하는 동안
다른 스레드가 접근하지 못하게 만든다. 만약 접근을 시도하면, 해당 스레드는 잠금이 해제될 때까지 대기하게 된다.
2. 해제 (Unlock)
: 작업이 끝나고 나면, 스레드는 뮤텍스를 해제하며, 대기 중인 스레드가 자원에 접근할 수 있게 된다.
이 잠금과 해제 과정을 통해서 다중 스레드가 순차적으로 공유 자원에 접근하여 어떠한 데이터의 오류 없이
제어할 수 있도록 해주는 것이 뮤텍스의 동작이다.
뮤텍스 함수
1. pthread_mutex_init()
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
: 뮤텍스를 초기화하는 함수.
pthread_mutex_t 로 선언된 mutex 객체의 포인터를 인자로 받고,
pthread_mutexattr_t 로 지정된 속성으로 뮤텍스를 초기화한다. (NULL 일 경우 기본 속성)
성공시 0 반환, 실패 시 에러코드 errno 를 반환한다.
2. pthread_mutex_lock()
int pthread_mutex_lock(pthread_mutex_t *mutex);
: 뮤텍스를 잠그는 함수.
만약 뮤텍스가 이미 잠긴 상태라면, 잠금이 풀릴 때까지 해당 스레드는 대기한다.
pthread_mutex_t 로 선언된 mutex 객체의 포인터를 인자로 받는다.
성공시 0 반환, 실패 시 에러코드 errno 를 반환한다.
3. pthread_mutex_unlock()
int pthread_mutex_unlock(pthread_mutex_t *mutex);
: 뮤텍스를 해제하는 함수.
lock으로 걸어둔 뮤텍스의 잠금을 해제하면, 다른 대기 중인 스레드가 뮤텍스를 잠글 수 있게 된다.
pthread_mutex_t 로 선언된 mutex 객체의 포인터를 인자로 받는다.
성공시 0 반환, 실패 시 에러코드 errno 를 반환한다.
4. pthread_mutex_destroy()
int pthread_mutex_destroy(pthread_mutex_t *mutex);
: 뮤텍스를 해제하여 더 이상 사용하지 않도록 하는 함수.
뮤텍스를 더 이상 사용하지 않을 때 호출하고, 뮤텍스 리소스를 해제하고 반환한다. (메모리 free X)
pthread_mutex_t 로 선언된 mutex 객체의 포인터를 인자로 받는다.
성공시 0 반환, 실패 시 에러코드 errno 를 반환한다.
사용 예시 - 1) mutex를 사용하지 않은 경우
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int shared_resource = 0;
pthread_mutex_t mutex;
void* thread_function_A(void* arg) {
// pthread_mutex_lock(&mutex);
for (int i = 0; i < 10; i++) {
shared_resource++;
printf("thread_A: %d\n", shared_resource);
sleep(1);
}
// pthread_mutex_unlock(&mutex);
return NULL;
}
void* thread_function_B(void* arg) {
// pthread_mutex_lock(&mutex);
for (int i = 0; i < 10; i++) {
shared_resource++;
printf("thread_B: %d\n", shared_resource);
sleep(1);
}
// pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[2];
// pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, thread_function_A, NULL);
sleep(1);
pthread_create(&threads[1], NULL, thread_function_B, NULL);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
// pthread_mutex_destroy(&mutex);
printf("shared_resource = %d\n", shared_resource);
return 0;
}
출력 - std_output)

mutex를 주석처리하여 실행해본 결과이다.
두 스레드를 각각 다른 함수를 동작하도록 해줬는데, 공유 자원인 shared resource를 늘려가는 동작은 동일하다.
하지만 스레드 두 개가 같은 공유 자원을 거의 동시에 추가해주며 교차적으로 실행되는 모습을 볼 수 있다.
이는 스레드의 공유자원 사용이 충돌 될 수 있고 공유 자원 값에 문제가 발생할 여지가 있는 모습이다.
사용 예시 - 2) mutex를 사용한 경우
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int shared_resource = 0;
pthread_mutex_t mutex;
void* thread_function_A(void* arg) {
pthread_mutex_lock(&mutex);
for (int i = 0; i < 10; i++) {
shared_resource++;
printf("thread_A: %d\n", shared_resource);
sleep(1);
}
pthread_mutex_unlock(&mutex);
return NULL;
}
void* thread_function_B(void* arg) {
pthread_mutex_lock(&mutex);
for (int i = 0; i < 10; i++) {
shared_resource++;
printf("thread_B: %d\n", shared_resource);
sleep(1);
}
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[2];
pthread_mutex_init(&mutex, NULL);
pthread_create(&threads[0], NULL, thread_function_A, NULL);
sleep(1);
pthread_create(&threads[1], NULL, thread_function_B, NULL);
pthread_join(threads[0], NULL);
pthread_join(threads[1], NULL);
pthread_mutex_destroy(&mutex);
printf("shared_resource = %d\n", shared_resource);
return 0;
}
출력 - std_output)

하지만 뮤텍스를 사용한 상태에서는 thread_A가 먼저 공유자원을 선점해 lock하고 공유자원을 늘려주고,
unlock 함과 동시에 thread_B가 lock하며 공유자원을 가져와 사용한다.
이러한 과정이 공유자원을 사용하는 데에 있어 뮤텍스를 활용하여 문제발생을 막아주는 것이다.
'프로그래밍 > CS' 카테고리의 다른 글
[study] 서브넷 마스크 (Subnet mask) (0) | 2025.02.20 |
---|---|
[study] IP (Internet Protocol) (0) | 2025.02.20 |
[study] 스레드 (Thread) (2) | 2024.08.31 |
[study] 프로세스 (Process) (2) | 2024.06.02 |
[study] Virtual box server 구축 개념 정리 (1) | 2024.05.08 |