1 minute read

쓰레드 생성

#include "ptrhead.h"

int pthread_create(pthread_t      *thread,
                   pthread_attr_t *attr,
                   void           (*start_routine)(void *),
                   void           *arg);
  • thread는pthread_t 타입 구조체를 가리키는 포인터이다.
    • 쓰레드와 상호작용하는 데 사용된다.
  • attr은 쓰레드 속성을 지정하는 데 사용한다.
    • 스택의 크기와 쓰레드들의 스케줄링 우선순위 같은 정보를 지정할 수 있다.
  • start_routine은 실행할 함수를 나타내는 함수포인터이다.
  • arg는 실행할 함수에 인자로 전달할 수 있다.

쓰레드 종료

int pthread_join(pthread_t thread, void **value_ptr);
  • 다른 쓰레드가 작업을 완료할 때까지 기다린다.
    • 두 개의 인자 중 첫 번째인 thread는 어떤 쓰레드를 기다리라고 하는지 명시하는 것이다.
    • value_ptr은 반환값에 대한 포인터이다. 임의의 데이터를 반환할 수 있기에 void *타입으로 사용된다.
      • 쓰레드의 콜 스택에 할당된 값을 가리키는 포인터를 반환하는 실수를 하지 않도록 한다.
  • 특정 작업을 병렬적으로 실행하기 위해 쓰레드를 생성하는 병렬 프로그램의 경우 종료 혹은 다음 단계로 넘어가기 전에 병렬 수행 작업이 모두 완료되었다는 것을 확인하기 위해 join을 사용한다.

pthread_mutex_t lock;
pthread_mutex_lock(&lock);
x = x + 1; // 임계영역 코드
pthread_mutex_unlock(&lock);
  • pthread_mutex_lock()가 호출되었을 때 다른 어떤 스레드도 락을 가지고 있지 않다면 이 쓰레드가 락을 얻어 임계 영역에 진입할 수 있다.
    • 많은 쓰레드들이 락 획득 과정에서 대기중일 수 있으며, 락을 획득한 쓰레드만이 언락을 호출해야 한다.
  • 락을 사용하기 전에 초기화하도록 한다. ```c pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

int rc = pthread_mutex_init(&lock, NULL); assert(rc == 0);

int rc = pthread_utex_lock(mutex) assert(rc == 0);

- 이 루틴의 첫번째 주소는 락 자체의 주소이고, 두 번째 인자는 선택가능한 속성이다.
- 실제 복잡한 프로그램에서, 락이나 언락이 실패한 경우 그냥 종료하면 안되고 적절한 대응을 하도록 한다.

## 컨디션 변수
- 한 쓰레드가 계속 진행하기 전에 다른 쓰레드가 무언가를 해야 하는 쓰레드 간에 일종의 시그널 교환 메커니즘이 필요할 때 컨디션 변수가 사용된다.
```c
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_mutex_signal(pthread_cond_t *cond);
  • 컨디션 변수를 사용하기 위해서는 컨디션 변수와 연결된 락이 반드시ㅈ 존재해야 한다. ```c pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHRAD_COND_INITIALIZER;

pthread_mutex_lock(&lock); while (ready == 0) Pthread_cond_wait(&cond, &lock); Pthread_mutex_unlock(&lock); ```

  • pthread_cond_wait()는 호출 쓰레드를 수면(sleep)상태로 만들고 다른 쓰레드로부터 시그널을 대기한다. 현재 수면 중인 쓰레드가 관심 있는 무언가가 변경되면 시그널을 보낸다.
  • 시그널을 보내고 전역 변수 ready를 수정할 때 반드시 락을 가져야 한다.
  • 시그널 대기 함수는 락을 두번째 인자로 받고 있지만, 시그널 보내는 함수에서는 조건만을 인자로 받고 있다. 시그널 대기 함수는 호출 스레드를 재우는 것 외에도 락을 반납해야 하기 때문이다.
  • pthread_cond_wait()는 깨어나서 리턴하기 직전에 락을 다시 획득한다.
  • ready 변수를 체크할 때, while로 사용하는 것이 안전하다.