[42서울] philosophers : 스레드와 스레드 함수 알기

jabae·2022년 8월 10일
0

42Seoul

목록 보기
18/20

〰️ 스레드란?

이전에 정리했던 [TIL : 42] 운영체제, 프로세스와 스레드와 멀티 스레드에 스레드와 프로세스에 대해 정리되어 있는 것을 참고 하자. 간단히 정리하면 스레드란 프로세스 내에서 코드가 실행되는 흐름의 단위이다. 멀티스레드란 하나의 프로세스 내에서 둘 이상의 스레드가 동시에 작업을 수행하는 것이다.

예를 들어, 내가 int main(){}을 실행하면, 하나의 스레드가 실행되는 것이다.

과제에서 허용하는 스레드 함수를 사용하기 위해서는 <pthread.h> 헤더파일을 인클루드 해줘야 한다. 과제에 보면 처음 보는 함수들이 많은데 일단 정리하고 들어가는 게 좋을 것 같아서 정리해 보았다.

🗄 스레드 함수

✅ pthread_create

새로운 스레드를 생성한다.

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 함수의 매개변수로 넘겨질 인자 
         );
  • return : 성공적으로 생성될 경우 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EGAIN : 스레드를 생성할 자원이 부족하거나, 시스템에 부과된 프로세스당 시스템 총 수[PTHREAD_THREADS_MAX]제한을 넘음
    • EPERM : 지정된 스케쥴링 정책이나 매개변수의 스케쥴링에 설정 권한이 없음
    • EINVAL : attr가 유효하지 않음

✅ pthread_detach

스레드를 분리시킨다.

pthread_detach된 스레드는 종료되면 자동으로 자원 반납이 이루어져 자원 낭비와 메모리 누수를 방지할 수 있다.

int pthread_detach(
		 pthread_t thread // 분리시킬 스레드 식별자
         );
  • return : 성공하면 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EINVAL : 스레드가 JOINABLE 하지 않음
    • ESRCH : 해당 ID 스레드를 찾을 수 없음

✅ pthread_join

스레드의 종료를 기다린다. 스레드는 JOINABLE(default)로 설정되어 있어야 한다.

pthread_join된 스레드(종료된 스레드)는 해당 스레드가 종료될 때까지 기다렸다가 종료되면 다음 스레드를 진행한다. 즉, 스레드의 종료까지 메인 스레드를 blocking한다. 매개변수로 스레드의 리턴값을 받아올 수 있고, 모든 자원을 반납하여 자원낭비와 메모리 누수를 방지한다.

int pthread_join(
		 pthread_t thread, // 기다릴 스레드 식별자
         void **value_ptr  // 종료 상태를 저장함. NULL이 아니라면, 스레드의 리턴값을 저장
         );
  • return : 성공하면 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EINVAL : 스레드가 JOINABLE 하지 않음
    • ESRCH : 해당 ID 스레드를 찾을 수 없음
    • EDEADLK : 데드락(교착 상태)가 감지되었음

✅ pthread_mutex_init

뮤텍스 객체를 생성한다.

int pthread_mutex_init(
		 pthread_mutex_t *mutex,         // 초기화시킬 뮤텍스
         const pthread_mutexattr_t *attr // 초기화 시킬 때 뮤텍스의 특성을 정의함. (기본특성 지정은 NULL)
         );
  • return : 성공하면 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EINVAL : attr가 유효하지 않음
    • ENOMEM : 프로세스 메모리가 충분하지 않아 뮤텍스를 생성할 수 없음

✅ pthread_mutex_destroy

뮤텍스 객체를 파괴한다. mutex 사용이 끝나면 할당된 자원을 해제시킨다.

int pthread_mutex_destroy(
		 pthread_mutex_t *mutex // 파괴할 뮤텍스
         );
  • return : 성공하면 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EINVAL : 뮤텍스가 유효하지 않음
    • EBUSY : 뮤텍스가 잠김상태

✅ pthread_mutex_lock

뮤텍스 객체를 lock시킨다. 뮤텍스가 이미 lock되어 있다면, 호출하는 스레드는 뮤텍스가 해제될 때까지 block된다.

즉, 임계구역에 하나의 스레드만 접근할 수 있도록 lock을 걸어준다.

int pthread_mutex_lock(
		 pthread_mutex_t *mutex // lock할 뮤텍스
         );
  • return : 성공하면 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EINVAL : 뮤텍스가 유효하지 않음
    • EDEADLK : 스레드가 뮤텍스 대기를 위해 블락하면 데드락(교착 상태)가 발생함

❓임계 구역(critical section)
둘 이상의 스레드가 동시에 접근해서는 안되는 공유 자원에을 접근하는 코드의 일부이다. 따라서 임계구역에 들어가거나 빠져나올 때, 동기화 기법을 사용해 데이터 레이스를 피해야 한다.

✅ pthread_mutex_unlock

뮤텍스를 unlock시킨다

int pthread_mutex_unlock(
		 pthread_mutex_t *mutex // unlock할 뮤텍스
         );
  • return : 성공하면 0, 실패할 경우 에러코드 값을 리턴
  • errors
    • EINVAL : 뮤텍스가 유효하지 않음
    • ENOMEM : 현재 스레드가 잠긴 뮤텍스를 소유하고 있지 않음

그 외

✅ gettimeofday

마이크로초 단위까지의 시간을 가져온다. 헤더 #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 */
       };
  • return : 성공하면 0, 실패할 경우 -1
profile
it's me!:)

0개의 댓글