Thread에 대하여 - C언어 기준으로

두비니

·

2021. 5. 6. 20:16

 


Thread에 대하여


 

 

 

 

1. Introduction

 

우선 Thread를 이야기 할 때 항상 거론되는 Process에 대해서 간단히 이야기해봅시다. Process에 대해서는 앞서 글을 써놨으니 참고합시다.

 

C언어에서 가장 대표적으로 프로세스를 생성할 때 쓰는 함수는 fork()입니다. 그러나 이 과정은 매우 비쌉니다.(자원의 측면에서)

우선 프로세스라는 것 자체가 자원을 공유하지 않고 각각의 code, data 등을 가지기 때문에 기존의 process의 것들을 다 복사를 해 주어야 합니다. 이걸 해결하기 위해 COW(Copy on Write)방법같은것도 고안되었지만, 만족스러운 수준까지 성능이 향상되지는 않았습니다. 그래봤자 page table이라던가 file descriptor table같은건 복사해주어야하니까요. 

 

그래서! 이런 상황에서 효율을 높이기 위해 고안된 것이 Thread입니다.

 

 

2. Thread 개념소개

 

Thread를 C언어 기준으로 설명할거라, 전체적인 설명은 간단히 하고 넘어가도록 하겠습니다.

앞서 말했듯이 자원을 공유하지 않아 비용이 비싼 process의 단점을 보완하기 위해 나온 것이 thread입니다. 

그러면 당연히 일부 데이터를 공유하겠죠?

 

 

이렇게 모든 thread들은 data와 code영역은 같이 공유하게 됩니다. 그러면 자연스럽게 이런 데이터를 사용하는 비용은 줄어들고요. 그래서 빨라진다는 장점도 있구요.(이론상 10배 빠르다고 합니다)

다만 이런 방법의 가장 큰 문제는 데이터의 일관성 문제가 생깁니다. 다 같은 자원을 쓰니깐 이게 내가 쓰려던 데이터가 맞나?라는 물음이 생기는거죠.

이런 관련 기법을 synchronization이라고 합니다. 

 

 

3. pthread.h

 

C언어에서는 이런 thread관련 API를 제공해주고 있습니다. 보통 pthread.h에서 많이 끌어다 쓰는데, 다음은 주요 함수들입니다. 

 

 

몇가지만 자세히 봐봅시다.

 

1) thread 생성 : pthread_create

새로운 프로세스 생성하기

 

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);

 

  • thread : 생성되었을 때 식별하기 위한 식별자 이름
  • attr : thread의 특성을 부여하기 위해 사용됨. 근데 보통 NULL로 지정.
  • start_routine : thread를 생성할 때 분기시킨 후, 실행할 함수
  • arg : start의 함수에 넘어가지는 매개변수 값
  • 리턴 값 : 성공이면 0, 아니면 0이 아닌 수

pthread_create()함수가 생성된 뒤로는, 특정 스레드가 사용될 것이라는 보장이 없음.

즉, race condition이 발생할 수 있음. 

따라서 synchronization technique는 필수

 

 

2) thread 제거 : pthread_exit, pthread_cancel 등등

 

thread는 만들고 난 뒤에 당연히 없앨 필요도 있겠죠. thread가 종료하는 시나리오는 다음과 같습니다.

 

  • thread의 start_routine이 return을 수행하여 thread가 종료됨.
  • thread가 pthread_exit()을 호출
  • thread가 pthread_cancel()을 통해 취소됨
  • 여러개의 thread중 하나라도 exit()을 호출하면, main thread가 return을 호출함.
    • main thread가 return을 호출한다 = 모든 thread가 즉시 종료됨.

 

 

3) thread 반환 기다리기 : pthread_join

 

void pthread_join(pthread_t thread, void **retval);

 

  • thread : exit을 기다릴 thread 식별자
  • retval : thread가 종료되면서 전달하는 인자

 

여기서 pthread_exit과 같이 자주 쓰이는 함수가 있습니다.

A와 B thread가 있다고 할 때, A가 B에 대해서 pthread_join을 건다고 가정하면, A thread는 B thread가 종료된 뒤에 실행됩니다. 약간 process에서 쓰던 wait()함수랑 비슷하죠?

 

 

각 함수들에 대한 예제들도 이어서 올리도록 하겠습니다. 끝!