이전에 정리했던 [TIL : 42] 운영체제, 프로세스와 스레드와 멀티 스레드에 스레드와 프로세스에 대해 정리되어 있는 것을 참고 하자. 간단히 정리하면 스레드란 프로세스 내에서 코드가 실행되는 흐름의 단위이다. 멀티스레드란 하나의 프로세스 내에서 둘 이상의 스레드가 동시에 작업을 수행하는 것이다.
예를 들어, 내가 int main(){}
을 실행하면, 하나의 스레드가 실행되는 것이다.
과제에서 허용하는 스레드 함수를 사용하기 위해서는 <pthread.h>
헤더파일을 인클루드 해줘야 한다. 과제에 보면 처음 보는 함수들이 많은데 일단 정리하고 들어가는 게 좋을 것 같아서 정리해 보았다.
새로운 스레드를 생성한다.
pthread_create
로 생성된 스레드는 메인 스레드가 종료되면 함께 종료된다. 자원을 반납하지 않으므로 메모리 누수가 발생한다.
pthread_detach
또는 pthread_join
을 사용해 생성된 스레드를 메인 스레드로 분리시켜 종료될 때 자원을 반납하도록 해야 메모리 누수가 발생하지 않는다.
int pthread_create(
pthread_t *thread, // 스레드 ID가 저장됨. 스레드 식별자로 사용
const pthread_attr_t *attr, // 스레드의 특성을 정의함. (기본특성 지정은 `NULL`)
void *(*start_routine)(void *), // 생성될 스레드가 실행할 함수
void *arg // start_routine 함수의 매개변수로 넘겨질 인자
);
EGAIN
: 스레드를 생성할 자원이 부족하거나, 시스템에 부과된 프로세스당 시스템 총 수[PTHREAD_THREADS_MAX]제한을 넘음EPERM
: 지정된 스케쥴링 정책이나 매개변수의 스케쥴링에 설정 권한이 없음EINVAL
: attr가 유효하지 않음스레드를 분리시킨다.
pthread_detach
된 스레드는 종료되면 자동으로 자원 반납이 이루어져 자원 낭비와 메모리 누수를 방지할 수 있다.
int pthread_detach(
pthread_t thread // 분리시킬 스레드 식별자
);
EINVAL
: 스레드가 JOINABLE
하지 않음ESRCH
: 해당 ID 스레드를 찾을 수 없음스레드의 종료를 기다린다. 스레드는 JOINABLE(default)
로 설정되어 있어야 한다.
pthread_join
된 스레드(종료된 스레드)는 해당 스레드가 종료될 때까지 기다렸다가 종료되면 다음 스레드를 진행한다. 즉, 스레드의 종료까지 메인 스레드를 blocking한다. 매개변수로 스레드의 리턴값을 받아올 수 있고, 모든 자원을 반납하여 자원낭비와 메모리 누수를 방지한다.
int pthread_join(
pthread_t thread, // 기다릴 스레드 식별자
void **value_ptr // 종료 상태를 저장함. NULL이 아니라면, 스레드의 리턴값을 저장
);
EINVAL
: 스레드가 JOINABLE
하지 않음ESRCH
: 해당 ID 스레드를 찾을 수 없음EDEADLK
: 데드락(교착 상태)가 감지되었음뮤텍스 객체를 생성한다.
int pthread_mutex_init(
pthread_mutex_t *mutex, // 초기화시킬 뮤텍스
const pthread_mutexattr_t *attr // 초기화 시킬 때 뮤텍스의 특성을 정의함. (기본특성 지정은 NULL)
);
EINVAL
: attr가 유효하지 않음ENOMEM
: 프로세스 메모리가 충분하지 않아 뮤텍스를 생성할 수 없음뮤텍스 객체를 파괴한다. mutex 사용이 끝나면 할당된 자원을 해제시킨다.
int pthread_mutex_destroy(
pthread_mutex_t *mutex // 파괴할 뮤텍스
);
EINVAL
: 뮤텍스가 유효하지 않음EBUSY
: 뮤텍스가 잠김상태뮤텍스 객체를 lock시킨다. 뮤텍스가 이미 lock되어 있다면, 호출하는 스레드는 뮤텍스가 해제될 때까지 block된다.
즉, 임계구역에 하나의 스레드만 접근할 수 있도록 lock을 걸어준다.
int pthread_mutex_lock(
pthread_mutex_t *mutex // lock할 뮤텍스
);
EINVAL
: 뮤텍스가 유효하지 않음EDEADLK
: 스레드가 뮤텍스 대기를 위해 블락하면 데드락(교착 상태)가 발생함❓임계 구역(critical section)
둘 이상의 스레드가 동시에 접근해서는 안되는 공유 자원에을 접근하는 코드의 일부이다. 따라서 임계구역에 들어가거나 빠져나올 때, 동기화 기법을 사용해 데이터 레이스를 피해야 한다.
뮤텍스를 unlock시킨다
int pthread_mutex_unlock(
pthread_mutex_t *mutex // unlock할 뮤텍스
);
EINVAL
: 뮤텍스가 유효하지 않음ENOMEM
: 현재 스레드가 잠긴 뮤텍스를 소유하고 있지 않음마이크로초 단위까지의 시간을 가져온다. 헤더 #include <sys/time.h>
에 있다. 필로소퍼의 죽음까지 정확한 시간을 알기 위해서 마이크로 초 단위의 시간이 필요하므로 timeval
사용법을 알아야 한다.
int gettimeofday(
struct timeval *restrict tp, // timeval 구조체
void *restrict tzp // timezone 구조체
);
restrict tp
: timeval 구조체struct timeval {
time_t tv_sec; /* seconds since Jan. 1, 1970 */
suseconds_t tv_usec; /* microseconds */
};
restrict tzp
: timezone 구조체struct timezone {
int tz_minuteswest; /* of Greenwich */
int tz_dsttime; /* type of dst correction to apply */
};