(리눅스 시스템 프로그래밍) OS Multithread Programming + C 예제코드
by 줌코딩
Thread란?
- Process 내부에 있는 single sequence stream이다.
- Process의 특징을 가지고 있기 때문에 lightweight process라고 불리기도 한다.
Thread와 Process의 차이
- Thread는 완전히 independent하지 않다.
- 다른 threads의 resource를 나눠쓴다.(code section, data section, resources)
- 하지만 여전히 개별 PC(program counter), register set, stack space를 가지고 있다.
왜 Multithreading을 하는가?
- 병렬구조를 사용하여 application을 향상시킨다.
- 예를 들어, window explorer의 여러개의 탭도 thread의 일부로 볼 수 있다.
- Thread는 process보다 훨씬 속도가 빠르다.
Thread가 Process보다 빠른 이유
- 생성이 빠르다.
- 쓰레드 간에 Context switching이 빠르다
- 쓰레드는 쉽게 종료된다.
- 쓰레드 간의 소통이 빠르다.
Threads in C
- C는 자바처럼 멀티쓰레딩을 지원하지 않는다.
- 그래서 pthread라는 POSIX standard for threads를 사용한다.
PThread Functions
pthread_create
Thread를 생성한다.
pthread_create(&thread_id, NULL, myThreadFun, NULL);
Arguments
- first : thread_t 변수의 주소값
- second : thread_t의 attribute
- third : 쓰레드가 실행시킬 함수
- fourth : 함수에게 전달할 파라미터
pthread_join
pthread_join(thread_id, NULL);
thread_id로 전달된 쓰레드가 종료되는 것까지 기다린다.
pthread_mutex_lock
int pthread_mutex_lock(pthread_mutex_t *mutex);
이 함수가 호출되면 호출한 thread가 mutex가 열릴 때가지 막는다.
pthread_mutex_unlock
int pthread_mutex_unlock(pthread_mutex_t *mutex);
막아져 있던 thread를 풀어준다.
pthread_cond_wait
pthread_cond_wait(&cond, &mutex);
시그널이 올 때까지 sleep하고 있다가 시그널이 오면 잠깐 mutex를 unlock한다.
pthread_cond_signal
pthread_cond_signal(&cond);
condition variable을 통해서 시그널을 보낸다.
main()
int main() {
pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
pthread_create( &thread1, NULL, print_message_function1, (void*) message1);
pthread_create( &thread2, NULL, print_message_function2, (void*) message2);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(0);
}
- line 2: pthread_t 라는 타입의 thread를 두개 생성해준다.
- line 7, 8: pthread_create 함수를 통해 thread를 생성해준다.
- line 10, 11: thread가 죽을 때까지 기다린다.
lock, signal, condition 활용 thread communication
- 각각 데이터를 3개씩 번갈아 가면서 출력해보자.
- 문제는 thread는 동시에 parallel하게 진행되기 때문에 순차적으로 진행되지 않는다.
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER ;
pthread_cond_t c1 = PTHREAD_COND_INITIALIZER ;
pthread_cond_t c2 = PTHREAD_COND_INITIALIZER ;
void *print_message_function1( void *ptr ){
char *message;
message = (char *) ptr;
int i = 0 ;
for (i = 0 ; i < 3 ; i++) {
printf("%s\n", message) ;
printf("%s\n", message) ;
printf("%s\n", message) ;
pthread_mutex_lock(&m) ;
pthread_cond_signal(&c2) ;
pthread_mutex_unlock(&m) ;
pthread_mutex_lock(&m) ;
pthread_cond_wait(&c1, &m) ;
pthread_mutex_unlock(&m) ;
}
}
void *print_message_function2( void *ptr ){
char *message;
message = (char *) ptr;
int i = 0 ;
for (i = 0 ; i < 3 ; i++) {
pthread_mutex_lock(&m) ; // racy
pthread_cond_wait(&c2, &m) ;
pthread_mutex_unlock(&m) ;
printf("%s\n", message) ;
printf("%s\n", message) ;
printf("%s\n", message) ;
pthread_mutex_lock(&m) ;
pthread_cond_signal(&c1) ;
pthread_mutex_unlock(&m) ;
}
}
- Line 16, 32: 1번 함수 출력이 끝나면 c2라는 condition변수를 이용해서 signal을 보내고 2번 함수 thread를 unlock해준다.
- Line 40, 20: 2번 함수 출력이 끝나면 c1이라는 condition 변수를 이용해서 1번함수에 signal을 보내고 1번 함수의 20번째 줄부터 unlock해준다.
이렇게 서로 시그널을 주고 받으면서 순차적으로 출력을 마무리한다.
결과 확인
pthread는 compile시 -pthread 옵션을 추가해준다.
jeongjinhyeog-ui-MacBook-Pro:Pthread jeongjinhyeog$ gcc -pthread pthread4.c
jeongjinhyeog-ui-MacBook-Pro:Pthread jeongjinhyeog$ ./a.out
Thread 1
Thread 1
Thread 1
Thread 2
Thread 2
Thread 2
Thread 1
Thread 1
Thread 1
Thread 2
Thread 2
Thread 2
보는 것과 같이 결과값이 각 함수당 3개씩 순차적으로 출력되는 것을 볼 수 있다!
느낀점
- thread는 정말 필요할 것 같다.
- thread와 process를 여러개 사용하는 차이점을 확실히 알아둬야 나중에 내가 뭘 써야할지 알 수 있을 것 같다.
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
Subscribe via RSS