pthread_mutex_init(&forks[i], NULL);는 POSIX 스레드(pthread)에서 뮤텍스(mutex)를 초기화하는 함수입니다. 이 호출을 하나씩 분석하고, 내부 동작, 옵션 설정, 사용 예제를 상세히 설명해 보겠습니다.
🔹 1. pthread_mutex_init() 함수 개요
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
✅ 매개변수
- pthread_mutex_t *mutex → 초기화할 뮤텍스 객체의 주소
- const pthread_mutexattr_t *attr → 뮤텍스 속성(attribute) 지정 (기본값 사용 시 NULL)
✅ 반환 값
- 성공 시 0 반환
- 실패 시 오류 코드 반환
- EINVAL → attr가 올바르지 않은 경우
- EAGAIN → 시스템 자원이 부족한 경우
- ENOMEM → 메모리 부족
🔹 2. &forks[i]의 의미
pthread_mutex_t forks[5]; // 뮤텍스 배열 선언 (철학자 5명 기준)
pthread_mutex_init(&forks[i], NULL);
- forks[i]는 i번째 뮤텍스 객체입니다.
- &forks[i]는 해당 뮤텍스 객체의 주소를 전달하여 초기화.
📌 즉, forks는 pthread_mutex_t의 배열이며, &forks[i]는 배열의 i번째 요소(뮤텍스)에 대한 참조를 전달합니다.
🔹 3. NULL 속성의 의미
pthread_mutex_init(&forks[i], NULL);
- 두 번째 인수 NULL은 기본 뮤텍스 속성(PTHREAD_MUTEX_DEFAULT)으로 설정됨.
- 기본적으로 빠른(mutual exclusion) 뮤텍스가 사용됨.
📌 속성을 직접 설정하고 싶다면 pthread_mutexattr_t 사용
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); // 재귀적 뮤텍스 설정
pthread_mutex_init(&forks[i], &attr);
pthread_mutexattr_destroy(&attr); // 속성 객체 제거
🔹 4. 동작 과정 (예제 포함)
✅ 예제: 5개의 철학자가 포크를 사용하도록 뮤텍스를 초기화하는 경우
#include <stdio.h>
#include <pthread.h>
#define NUM_FORKS 5
pthread_mutex_t forks[NUM_FORKS]; // 포크(뮤텍스) 배열
int main() {
// 뮤텍스 초기화
for (int i = 0; i < NUM_FORKS; i++) {
if (pthread_mutex_init(&forks[i], NULL) != 0) {
perror("Mutex init failed");
return 1;
}
}
printf("All mutexes initialized successfully.\n");
// 사용이 끝난 후 뮤텍스 제거
for (int i = 0; i < NUM_FORKS; i++) {
pthread_mutex_destroy(&forks[i]);
}
return 0;
}
✅ 실행 흐름
- pthread_mutex_t forks[NUM_FORKS]; → 5개의 뮤텍스를 배열로 선언.
- pthread_mutex_init(&forks[i], NULL);을 통해 각 뮤텍스를 초기화.
- 모든 뮤텍스가 사용된 후 pthread_mutex_destroy(&forks[i]);로 해제.
🔹 5. 메모리 할당 방식
pthread_mutex_t forks[5];은 **정적 할당(Static Allocation)**을 사용합니다.
하지만 동적으로 할당할 수도 있습니다.
✅ 동적 할당 예제
pthread_mutex_t *forks = malloc(sizeof(pthread_mutex_t) * NUM_FORKS);
for (int i = 0; i < NUM_FORKS; i++) {
pthread_mutex_init(&forks[i], NULL);
}
// 뮤텍스 사용 후 해제
for (int i = 0; i < NUM_FORKS; i++) {
pthread_mutex_destroy(&forks[i]);
}
free(forks);
✅ 차이점
- 배열 선언 시(pthread_mutex_t forks[5];) → 컴파일 시 크기 결정됨.
- 동적 할당(malloc()) → 런타임에 크기 조정 가능.
🔹 6. 실패 처리 및 디버깅
pthread_mutex_init()은 실패할 수 있으므로 반환 값을 반드시 체크해야 합니다.
if (pthread_mutex_init(&forks[i], NULL) != 0) {
perror("Mutex initialization failed");
}
⚠ 디버깅 포인트
- 뮤텍스를 초기화하기 전에 사용하면 오류 발생
- pthread_mutex_destroy()를 호출하지 않으면 메모리 누수 가능
🔹 7. pthread_mutex_init()을 여러 번 호출하면?
pthread_mutex_init(&forks[i], NULL);
pthread_mutex_init(&forks[i], NULL); // ⚠ 두 번 초기화 (잘못된 사용)
⚠ 결과: 정의되지 않은 동작(Undefined Behavior)
- 같은 뮤텍스를 여러 번 초기화하면 동작이 보장되지 않음.
- 초기화 전 반드시 pthread_mutex_destroy() 호출해야 함!
🔹 8. 정리
개념 설명
pthread_mutex_init() | 뮤텍스를 초기화 |
&forks[i] | forks 배열의 i번째 뮤텍스의 주소 |
NULL 속성 | 기본 속성(PTHREAD_MUTEX_DEFAULT) 사용 |
반환 값 | 성공 시 0, 실패 시 오류 코드 반환 |
동적 할당 가능 | malloc()을 사용하여 동적 할당 가능 |
초기화 전 파괴 필요 | 기존 뮤텍스를 다시 초기화하려면 pthread_mutex_destroy() 필요 |
🚀 즉, pthread_mutex_init(&forks[i], NULL);은 i번째 뮤텍스를 기본 설정으로 초기화하는 코드!
'C Language' 카테고리의 다른 글
mutex 입금문제 (2) | 2025.03.13 |
---|---|
eat 함수 (0) | 2025.03.13 |
뮤텍스 포인터 차이 (0) | 2025.03.13 |
mutex 잠금 원리 (0) | 2025.03.13 |
pthread_mutex_lock pthread_mutex_unlock 설명 (0) | 2025.03.12 |