Researcher to Developer

Pthread - create, exit, join, detach, mutex 본문

코딩/Basic

Pthread - create, exit, join, detach, mutex

Probe29 2021. 1. 3. 18:09

#Pthread

리눅스에서 Thread를 생성하고 관리하는 함수

 

- thread 표준 API

POSIX 스레드 또는 Pthread 라고 부른다.

 

- Pthread API

저수준 API로 100 여개의 함수 제공
복잡하지만 유닉스 시스템 핵심 스레딩 라이브러리
다른 스레딩 솔루션도 결국 Pthread 를 기반으로 구현되어 있으므로 익혀둘 가치가 있다.

pthread API는 Semaphore를 포함하지 않는다.

 

리눅스 C언어에서는 어떻게 Pthread를 사용할 수 있을까?

 

 

 

 

#Pthread 라이브러리


헤더 파일 <pthread.h>
모든 함수는 pthread_ 로 시작한다.
크게 두 가지 그룹으로 나뉜다. 
1. 스레드 관리 : 생성, 종료, 조인, 디태치 함수 등
2. 동기화 : 뮤텍스 등 동기화 관련 함수

기본 라이브러리 (glibc) 와 분리된 libpthread 라이브러리에 pthread 구현되어 있으므로
컴파일시 명시적으로 pthread 옵션이 필요하다.

gcc test.c -o test 기본 라이브러리에서 컴파일시 사용했던 함수
gcc -pthread test.c -o test  libpthread 라이브러리에서 컴파일시 사용해야 하는 함수

 

 

 

 

#스레드 create

 

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

// thread 생성된 스레드 식별자
// attr 스레드 특정 설정 (기본 NULL)
// start_routine 스레드 함수 (스레드로 분기해서 실행할 함수)
// arg 스레드 함수 인자

코드 예제는 다음과 같다.

pthread_t thread1;
void *thread_function(void *ptr);

ret = pthread_create(&thread1, NULL, thread_function, (void*)message1);

인자들을 살펴보면
&thread1 : 해당 스레드를 가리키는 포인터를 나타내고
NULL : 스레드의 특정한 설정이 필요한 곳(대부분 NULL)
thread_function : 정의된 함수를 넣는 곳
(void*)message1) 

 

 

 

 

#스레드 exit

 

void pthread_exit(void *retval);    // exit 와 유사, NULL 또는 0은 정상 종료

코드 예제는 다음과 같다. 

pthread_exit(NULL);

 

 

 

 

#스레드 Join

 

리눅스에서 본래 프로세스는 메인스레드라고 지칭한다.
pthread_create 코드로 새로운 스레드를 추가로 생성하게 된다.
만약 2개의 스레드가 추가로 생성이 되었다고 치면
원래는 추가된 스레드의 코드가 실행이 되고 종료되면 메인 스레드의 다음 코드를 읽어나가야하는데
추가된 스레드 중 아직 실행중인 스레드가 있다면 비정상적으로 동작할 수 있기 때문에
남은 실행중인 스레드가 끝날때까지 기다리는 코드가 있다.

 

 

int pthread_join(pthread_t thread, void **thread_return);
// thread 기다릴 스레드 식별자
// thread_return 스레드의 리턴 값을 가져올 수 있는 포인터

코드 예제는 다음과 같다.

pthread_join(p_thread, (void *)&status);
printf("thread join : %d\n", status);

p_thread 식별자를 가진 스레드의 종료를 기다리고, status 포인터로 종료값을 가져옴 

 

 

 

 

 

#스레드 detach

 

해당 스레드가 종료될 경우, 즉시 관련 리소스를 해체한다.

pthread_join 를 기다리지 않고, 종료 즉시 리소스를 해제한다.

int pthread_detach(pthread_t thread);
// thread : datach할 스레드 식별자

 

 

 

 

 

#스레드 join vs detach

join과 detach를 구분해서 정리할 필요가 있다.

 

join code

를 사용하면 스레드 1이 끝나야 스레드 2가 시작하는 것을 확인할 수 있다. 

detach code

를 사용하면 다음 코드를 무작정 실행하도록 한다. 

하지만 join이나 datach나 결국에는 메모리를 해제한다.

 

 

 

1. 리소스 관점

 

pthread_join 
를 호출한다는 것은 메인 스레드에서 추가로 생성된 해당 스레드가 종료되고 
상태값을 보고 + 추가 처리까지 해주겠다는 것을 의미

pthread_detach 
를 호출한다는 것은 추가로 생성된 해당 스레드가 종료되면

그 스레드 리소스를 바로 해제한다. 별도 작업이 없다는 의미 



2. 실행 관점

pthread_join  
join 다음에 있는 코드는 포인터에 쓰인 스레드가 종료되지 않으면 읽지않는다.
종료될 때 까지 기다린다는 의미

pthread_detach  
detach 다음에 있는 코드가 포인터에 쓰인 스레드가

종료될 때까지 기다리지 않는다는 의미

 

 

 



#Pthread 뮤텍스 - 상호 배제 기법, 동기화 관련

뮤텍스 선언과 초기화

pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t 타입으로 선언
mutex_lock 변수

 


뮤텍스 락 걸기/풀기

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

 

 

상호 배제가 보장되는 라인

x = go_beyond(x);