4. Threads
๋ค๋ฃจ๋ ์ฃผ์
- A. ์ค๋ ๋ ๊ฐ๋
- B. ๋ฉํฐ์ค๋ ๋ฉ ๋ชจ๋ธ
- C. ์ค๋ ๋ฉ ๊ด๋ จ ์ด์
- D. ์ฌ๋ก
A. ์ค๋ ๋ ๊ฐ๋
๊ฐ๋
- ์ค๋ ๋๋ ํํ ๊ฒฝ๋ ํ๋ก์ธ์ค(lightweight process)๋ผ ๋ถ๋ฆผ
- ์คํ์ ๋จ์ (์ค์ผ์ค๋ง์ ๋จ์)
- ์ต์ํ์ ์์๋ง์ ํ์๋ก
- ์ ํต์ ์ธ ํ๋ก์ธ์ค๋ ์ค๋ ํ๋ก์ธ์ค(heavyweight process)๋ผ ๋ถ๋ฆผ

ํ๋ก์ธ์ค vs. ์ค๋ ๋
- ํ๋ก์ธ์ค
- ์คํ ๋จ์ (์ค์ผ์ค๋ง ๋จ์)
- ์์ ํ ์์ ์์ ๊ถ์ ๊ฐ์ง
- ์ฃผ์ ๊ณต๊ฐ๊ณผ ํ๋ก์ธ์ ์ปจํ ์คํธ(context) ๋ณด์
- ์์(ํ์ผ, I/O ์ฅ์น ๋ฑ)์ ๋ํ ์ ์ด๊ถ ๋ณด์
- ์ค๋ ๋
- ์คํ ๋จ์ (์ค์ผ์ค๋ง ๋จ์)
- ์คํ์ ํ์ํ ์ต์ํ์ ์์๋ง์ ํ์๋ก
- private ์คํ(private stack) ๊ณต๊ฐ๊ณผ ํ๋ก์ธ์ ์ปจํ ์คํธ ๋ณด์
- ํ๋ก์ธ์ค์ ๋ค๋ฅธ ์์๋ค์ ๊ณต์
๋จ์ผ ์ค๋ ๋ vs. ๋ฉํฐ ์ค๋ ๋ ์ ํ๋ฆฌ์ผ์ด์

์ค๋ ๋ ์์ โ ์์ฑ๊ณผ ์ข ๋ฃ
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid) {
printf("\n%d: Hello World!\n", threadid);
pthread_exit(NULL);
}
int main (int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc, t;
for(t=0; t < NUM_THREADS; t++){
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
int
pthread_create (pthread_t *thread_id,
const pthread_attr_t *attr,
void *(*thread_function)(void *),
void *arg);
pthread_createํจ์ ๋ถ์
thread_id์ธ์๋ฅผ ํตํด ์๋ก์ด ์ค๋ ๋ ID๋ฅผ ๋ฐํattrํ๋ผ๋ฏธํฐ๋ ์ค๋ ๋ ์์ฑ์ ์ค์ ํ๋ ๋ฐ ์ฌ์ฉ๋จ (๊ธฐ๋ณธ๊ฐ์ NULL)thread_func๋ ์ค๋ ๋๊ฐ ์์ฑ๋ ํ ์คํํ C ๋ฃจํด์arg๋ฅผ ํตํดstart_routine์ ๋จ์ผ ์ธ์๋ฅผ ์ ๋ฌํ ์ ์์
Pthreads APIs
pthread_t pthread_self(): ์์ ์ ์ค๋ ๋ ID๋ฅผ ๊ฐ์ ธ์ดint pthread_equal(pthread_t t1, pthread_t t2): ๋ ์ค๋ ๋ ID๋ฅผ ๋น๊ตint pthread_join(pthread_t thread, void status_ptr): ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ข ๋ฃ๋ ๋๊น์ง ๋๊ธฐint pthread_detach(pthread_t thread): ์ค๋ ๋๊ฐ ์ข ๋ฃ๋ ๋ ํ ๋น๋ ์์์ ์ฆ์ ํ์ํ ์ ์์์ ๋ํ๋ (๋ถ๋ฆฌ๋ ์ค๋ ๋๋ join๋ ์ ์์)
์ค๋ ๋์ ์คํ ํน์ฑ
- ์ค๋ ๋๋ ์คํ ์ํ(์คํ ์ค, ์ค๋น, ๋๊ธฐ)๋ฅผ ๊ฐ์ง
- ์ค๋ ๋ ๋ฌธ๋งฅ ๊ตํ(context switching)์ด ํ์
- ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ(์ฝ๋ ๋ฐ ๋ฐ์ดํฐ)๊ณผ ์์์ ๊ณต์
- ํ ์ค๋ ๋๊ฐ ์ ์ญ ๋ณ์๋ฅผ ์์ ํ๋ฉด ํ๋ก์ธ์ค ๋ด ๋ค๋ฅธ ๋ชจ๋ ์ค๋ ๋๊ฐ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ธ ๊ฐ๋ฅ
- ํ ์ค๋ ๋๊ฐ ์ฐ ํ์ผ์ ๋ค๋ฅธ ์ค๋ ๋์์๋ ์ฌ์ฉ ๊ฐ๋ฅ
Thread Private Data
- ์คํ์ ์ ์ฅ๋๋ ๋ณ์๋ ์ค๋ ๋ private ๋ฐ์ดํฐ์
- ํจ์๋ก ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ ์ญ์ ์ค๋ ๋ private ๋ฐ์ดํฐ์ ํด๋น
double func( double a ) { double b; ...
- ํจ์๋ก ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ ์ญ์ ์ค๋ ๋ private ๋ฐ์ดํฐ์ ํด๋น
- ๋ณ์ a์ b๋ ๊ฐ ์ค๋ ๋์ ๋ํด ๋ ๋ฆฝ์ ์
์ค๋ ๋ ๋ก์ปฌ ๋ณ์ (Thread Local Variables)
- ๋ชจ๋ ๋ฃจํด์์ ์ ๊ทผ ๊ฐ๋ฅํ ์ ์ญ ๋ฐ์ดํฐ์ด๋, ๊ฐ ์ค๋ ๋๋ ๋ฐ์ดํฐ์ ๋
๋ฆฝ์ ์ธ ์ฌ๋ณธ๋ง์ ๊ฐ์ง
__thread void * mydata; void * threadFunction( void * param ) { mydata = param; ... mydata๋ณ์๋ ์ค๋ ๋์ ๋ก์ปฌํ๋ฏ๋ก, ๊ฐ ์ค๋ ๋๋ ํด๋น ๋ณ์์ ๋ํด ์๋ก ๋ค๋ฅธ ๊ฐ์ ๊ฐ์ง ์ ์์
์ด์ Benefits
- ์๋ต์ฑ (Responsiveness)
- ํ๋ก๊ทธ๋จ์ ์ผ๋ถ๊ฐ ์ฐจ๋จ(block)๋์ด๋ ๊ณ์ ์คํ ๊ฐ๋ฅ
- ์์ ๊ณต์ (Resource sharing)
- ๋ฉ๋ชจ๋ฆฌ์ ์์์ ๊ณต์
- ๊ฒฝ์ ์ฑ (Economy)
- ์์ฑ ๋ฐ ๋ฌธ๋งฅ ๊ตํ ๋น์ฉ์ด ์ ๋ ด
- ๋ฉํฐํ๋ก์ธ์ ์ํคํ
์ฒ ํ์ฉ
- ๋ฉํฐ์ค๋ ๋ ํ๋ก์ธ์ค๋ก ๋ณ๋ ฌ์ฑ ์ฆ๋ ๊ฐ๋ฅ
- ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ ์ ๊ณต
์์: ์น ์๋ฒ๋ฅผ ์ํ ๋ฉํฐ์ค๋ ๋ฉ

- ๋์คํจ์ฒ ์ค๋ ๋(Dispatcher Thread): ์์ฒญ์ ๋ฐ์ ์์ ์ค๋ ๋์ ์ ๋ฌ
- ์์
์ค๋ ๋(Worker Thread): ์ค์ ์์ฒญ์ ์ฒ๋ฆฌ(์บ์ ํ์ธ, ๋์คํฌ ์ฝ๊ธฐ ๋ฑ)


Processes, Threads, and Tasks
- ํ์คํฌ์ ์ฉ์ด์ ์ ์
- ์ด์์ฒด์ ์์ ํํ ์ฌ์ฉ๋๋ ์ ๋ฌธ ์ฉ์ด๋ ์๋
- ํ์ง๋ง ๋ง์ ์ฌ๋๋ค์ด ์คํ ๋จ์(unit of execution) ๋๋ ์ค์ผ์ค๋ง ๋จ์(unit of scheduling)๋ฅผ ์๋ฏธํ๋ ์ฉ์ด๋ก "ํ์คํฌ"๋ฅผ ์ฌ์ฉํจ
- ์ฌ์ฉ ๋งฅ๋ฝ
- ํ์ ์ด์์ฒด์ ์์ ์ค๋ ๋๋ฅผ ์ง์ํ๋์ง ์ฌ๋ถ์ ๊ด๊ณ์์ด ์ฌ์ฉ๋จ
- ์ด์์ฒด์ ๊ฐ ์ค๋ ๋๋ฅผ ์ง์ํ ๊ฒฝ์ฐ ์ค๋ ๋๋ฅผ ์๋ฏธํ ์ ์์
- ์ด์์ฒด์ ๊ฐ ์ค๋ ๋๋ฅผ ์ง์ํ์ง ์์ ๊ฒฝ์ฐ ํ๋ก์ธ์ค๋ฅผ ์๋ฏธํ ์ ์์
B. ๋ฉํฐ์ค๋ ๋ฉ ๋ชจ๋ธ
์ฌ์ฉ์ ์ค๋ ๋ (User Threads)
- ์ฌ์ฉ์ ์์ค์ ์ค๋ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํด ๊ด๋ฆฌ๋จ
- ์ปค๋์ ์ง์ ์์ด ์ด์๋จ
- ์ฅ์ : ์์ฑ ๋ฐ ๊ด๋ฆฌ๊ฐ ๋น ๋ฆ (์ปค๋ ๊ฐ์ ์์)
- ๋จ์ : ์ปค๋์ด ๋จ์ผ ์ค๋ ๋ ๋ฐฉ์์ผ ๊ฒฝ์ฐ, ํ๋์ ์ฌ์ฉ์ ์ค๋ ๋๊ฐ ์์คํ ์ฝ๋ก ์ฐจ๋จ๋๋ฉด ํ๋ก์ธ์ค ์ ์ฒด๊ฐ ์ฐจ๋จ๋จ
- ์ฌ๋ก: POSIX Pthreads, Mach C-threads
์ปค๋ ์ค๋ ๋ (Kernel Threads)
- ์ปค๋์ ์ํด ์ง์ ์ง์๋จ
- ์ปค๋์ด ์ปค๋ ๊ณต๊ฐ์์ ์ค๋ ๋ ์์ฑ, ์ค์ผ์ค๋ง, ๊ด๋ฆฌ๋ฅผ ์ํ
- ์ฌ์ฉ์ ์ค๋ ๋๋ณด๋ค ์์ฑ ๋ฐ ๊ด๋ฆฌ๊ฐ ๋๋ฆผ
- ์ฌ๋ก: Windows, Solaris, Linux ๋ฑ
๋ฉํฐ์ค๋ ๋ฉ ๋ชจ๋ธ์ ์ข ๋ฅ

- ๋ค๋์ผ(Many-to-One): ์ฌ๋ฌ ์ฌ์ฉ์ ์ค๋ ๋๊ฐ ํ๋์ ์ปค๋ ์ค๋ ๋์ ๋งคํ๋จ (์ปค๋ ์ค๋ ๋ ๋ฏธ์ง์ ์์คํ ์์ ์ฌ์ฉ)
- ์ผ๋์ผ(One-to-One): ๊ฐ ์ฌ์ฉ์ ์ค๋ ๋๊ฐ ๊ฐ๋ณ ์ปค๋ ์ค๋ ๋์ ๋งคํ๋จ (Windows, OS/2 ๋ฑ)
- ๋ค๋๋ค(Many-to-Many): ์ฌ๋ฌ ์ฌ์ฉ์ ์ค๋ ๋๊ฐ ๊ทธ๋ณด๋ค ์ ๊ฑฐ๋ ๊ฐ์ ์์ ์ปค๋ ์ค๋ ๋์ ๋งคํ๋จ (Solaris 2 ๋ฑ)
C. ์ค๋ ๋ฉ ๊ด๋ จ ์ด์
fork() ์์คํ ์ฝ์ ์๋ฏธ
- ํ ์ค๋ ๋๊ฐ
fork()๋ฅผ ํธ์ถํ ๊ฒฝ์ฐ ๋ ๊ฐ์ง ๊ฐ๋ฅ์ฑ์ด ์กด์ฌ- ์ ํ๋ก์ธ์ค๊ฐ ๋ชจ๋ ์ค๋ ๋๋ฅผ ๋ณต์
- ์ ํ๋ก์ธ์ค๊ฐ ๋จ์ผ ์ค๋ ๋๋ก ์์ฑ๋จ
- ๋ง์ ์์คํ
์ด ๋ ๊ฐ์ง ๋ณํ๋
fork()๋ฅผ ๋ชจ๋ ์ ๊ณตํ์ฌ ์ ์ถฉ
๊ธฐํ ์์คํ ์ฝ ๊ด๋ จ ์ด์
- ํ๋ก์ธ์ค ๋ด ๋ชจ๋ ์ค๋ ๋๋ ํ์ผ ๋์คํฌ๋ฆฝํฐ ์งํฉ์ ๊ณต์
- ํ ์ค๋ ๋๊ฐ ํ์ผ์ ๋ซ๋ ๋์ค ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ฝ๊ฑฐ๋ ์ฐ๋ ์ํฉ์ ๋ํ ํ์ผ ์ ๊ธ ํ๋กํ ์ฝ์ด ํ์
- ๊ณตํต ์ฃผ์ ๊ณต๊ฐ์ ๊ณต์
mmap,brk์ ๊ฐ์ ์์คํ ์ฝ์ ํตํ ๋์ ์์ ์ ์ค๋ ๋ ์์ (thread-safe)์ ๋ณด์ฅํด์ผ
์คํ ์ค๋ฒํ๋ก์ฐ (Stack Overflow)
- UNIX ํ๋ก์ธ์ค ์คํ ์ค๋ฒํ๋ก์ฐ ์ ์ปค๋์ด ์ด๋ฅผ ๊ฐ์งํ๊ณ ์๋ ํ์ฅ
- ์ฌ์ฉ์ ์ค๋ ๋์ ๊ฒฝ์ฐ ์ปค๋์ด ์ฌ์ฉ์ ์คํ ์ ๋ณด๋ฅผ ์์ง ๋ชป
- ์ฌ์ฉ์ ์ค๋ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์คํ ๋์ ์ฐ๊ธฐ ๋ฐฉ์ง ํ์ด์ง๋ฅผ ํ ๋นํ์ฌ ๋ณดํธ
- ์ค๋ฒํ๋ก์ฐ ๋ฐ์ ์ ๋ณดํธ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ณ ์ปค๋์ด SIGSEGV ์ ํธ๋ฅผ ํด๋น ์ค๋ ๋์ ๋ณด๋
์ค๋ ๋ ํ (Thread Pool)
- ํ๋ก์ธ์ค ์์ ์ ๋ฏธ๋ฆฌ ์ผ์ ์์ ์ค๋ ๋๋ฅผ ์์ฑํ์ฌ ํ์ ์ ์ฅ
- ์์ฒญ ๋ฐ์ ์ ํ์์ ์ค๋ ๋๋ฅผ ๊นจ์ ํ ๋นํ๊ณ , ์์ ์๋ฃ ํ ๋ค์ ํ๋ก ๋ฐํ
- ์ฅ์ : ์ ์ค๋ ๋ ์์ฑ๋ณด๋ค ์ฒ๋ฆฌ๊ฐ ๋น ๋ฅด๋ฉฐ, ์์คํ ์ด ์ง์ ๊ฐ๋ฅํ ์ค๋ ๋ ์๋ฅผ ์ ํํ ์ ์์
- ์น ์๋ฒ ๋ฉํฐ์ค๋ ๋ฉ์ ์ ์ฉ
D. ์ฌ๋ก
Solaris 2 ์ค๋ ๋
- ์ปค๋ ๋ฐ ์ฌ์ฉ์ ์์ค ๋ชจ๋์์ ์ค๋ ๋ ์ง์
- ์ฌ์ฉ์ ์ค๋ ๋์ ์ปค๋ ์ค๋ ๋ ์ฌ์ด์ ๊ฒฝ๋ ํ๋ก์ธ์ค(LWP)๊ฐ ์กด์ฌ
- LWP๋ ์ปค๋์ด ์ง์ํ๋ ์ฌ์ฉ์ ์ค๋ ๋์ด๋ฉฐ, ํ๋ก์ธ์ค๋ ์ต์ ํ๋ ์ด์์ LWP๋ฅผ ํฌํจ

- ์ปค๋ ์์ค ์ค๋ ๋
- LWP์ ์ฐ๊ฒฐ๋๊ฑฐ๋ ์ปค๋ ์์ฒด ์์ ์ ์ํด ์กด์ฌํ๋ฉฐ, ์์คํ ๋ด์์ ์ ์ผํ ์ค์ผ์ค๋ง ๋์
- ์ฌ์ฉ์ ์์ค ์ค๋ ๋
- ๋ฐ์ด๋(Bound): ํน์ LWP์ ์๊ตฌ์ ์ผ๋ก ์ฐ๊ฒฐ๋จ (๋น ๋ฅธ ์๋ต์ด ํ์ํ ์ค์๊ฐ ์ฑ์ฉ)
- ์ธ๋ฐ์ด๋(Unbound): ๊ธฐ๋ณธ๊ฐ์ผ๋ก, ๊ฐ์ฉํ LWP ํ์ ๋ฉํฐํ๋ ์ฑ๋์ด ์คํ๋จ
Solaris Process


