1. 프로세스의 문제점
작업/태스크(task) : 컴퓨터에서 처리하고자 하는 일의 단위
멀티태스킹(multi-tasking): 컴퓨터 시스템 내 여러 태스크(응용프로그램)을 동시에 실행시키거나 한 응용프로그램내에서 여러 태스크를 동시에 실행시키는 기법
- 동시에 여러 작업 처리 가능
- 동시에 실행되는 여러 개의 태스크를 관리해야하는 문제점
멀티태스킹의 문제점
- 프로세스 생성의 큰 오버헤드 : 생성에 많은 시간이 소요됨
- 프로세스 컨텍스트 스위칭의 큰 오버헤드
- 프로세스 사이의 통신 어려움
- 독립된 메모리 공간에서 실행되어 프로세스끼리 메모리 접근이 불가능 → 다양한 기법으로 데이터 공유 → 커널의 지원을 받아야 가능하여 호환성이 부족하고 어려움
2. 스레드 개념
2.1 스레드의 출현 목적
프로세스보다 작고 쉽게 데이터를 주고받을 수 있는 실행 단위 → 스레드(thread)
- 프로세스보다 작은 실행 단위 필요
- 프로세스의 생성 및 소멸에 따른 오버헤드 감소
- 빠른 컨텍스트 스위칭
- 프로세스들 사이의 통신에 대한 어려움 해소
멀티태스킹 문제점 해소
2.2 스레드 개념
멀티스레드 운영체제(multi-Threaded Operating System) : 스레드를 실행단위로 다루는 운영체제
- 스레드는 실행 단위이며 스케줄링 단위이다
- 개발자 : 작업을 만드는 단위, 운영체제 : 실행 단위&CPU를 할당하는 스케줄링 단위
- 코드, 데이터, 힙, 스택이 담긴 주소공간을 가진 실체
- 운영체제에 의해 실행 제어
- 스레드마다 TCP(Thread control Block) 구조체를 두고 독립된 단위로 스레드 관리
- 프로세스는 스레드들의 컨테이너이다
- 프로세스 → 컨테이너
- 프로세스 생성시 자동으로 프로세스 내 1개의 스레드 생성 → 메인 스레드
- 프로세스 실행 = 메인 스레드 실행
- 프로세스마다 PCB가 생성되고 스레드마다 TCB 구조체가 생성됨
- TCB = 스레드 엔티티, 스케줄링 엔티티
- 프로세스는 스레드들의 공유 공간 제공
- 스레드들은 프로세스의 주소 공간을 나누어 사용
- 프로세스 주소 공간 내 스레드 코드 적재
- 스레드들끼리 상호 데이터 공유 가능
- 기존 프로세스 사이에 데이터를 주고받는 어려움 해결
- 스레드가 실행할 작업은 함수로 작성한다
- 운영체제에게 함수를 스레드로 만들것을 요청 → 운영체제가 TCB를 만듦 → 함수의 시작주소 tcb에 기록
- tcb가 스케줄링되면 기록된 주소에서 실행 시작
- 스레드가 생성된다 = 커널 내 tcb가 생성된다
- 스레드와 프로세스의 생명
- 스레드로 만든 함수 종료 = 스레드 종료
- 프로세스에 속한 모든 스레드 종료 = 프로세스 종료, 할당된 메모리와 자원 제거
2.3 스레드 만들기
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* calcThread(void *param); // 스레드로 작동할 코드
int sum = 0; // main 스레드와 calcThread가 공유하는 전역 변수
int main() {
pthread_t tid;
pthread_attr_t attr; // 스레드 정보를 담을 구조체
pthread_attr_init(&attr); // 디폴트값으로 attr 초기화
pthread_create(&tid, &attr,calcThread, "100"); // calcThread 스레드 생성
// calcThread 스레드는 커널에 의해 언젠가 스케줄되어 실행
pthread_join(tid, NULL); // tid 번호의 스레드 종료를 기다림
printf("%d",sum);
}
void* calcThread(void *param){ // param에 100 전달받음
int to = atoi(param);
int i;
for(int i=1; i<=to; i++)
sum += i;
}
- 프로세스가 생성되면 자동으로 main 스레드가 생성된다
- main 스레드는 main() 함수를 실행한다
- 스레드 코드는 함수로 만들어진다
- 스레드는 phtread_craete()와같은 라이브러리 함수나 시스템 호출로 다른 스레드를 생성한다
- 스레드마다 TCB가 하나씩 생성된다
- TCB에는 스레드의 시작 주소가 들어있으며, 스레드의 실행은 이 주소에서 시작된다
- TCB가 하나의 스레드로 인식된다
- 스레드는 스케줄링되고 실행되는 실행 단위이다
- 프로세스는 더 이상 실행단위가 아니며 스레드들의 컨테이너이다
- 프로세스의 전역 변수는 모든 스레드에 의해 공유되며 프로세스는 스레드들에게 공유 공간을 제공한다
2.4 멀티스레드 응용프로그램 사례
각 스레드는 정해진 작업을 독립적으로 수행, 다른 스레드에게 데이터를 전달하면서 유기적으로 실행됨
2.5 멀티스레딩 분석
- 3개의 스레드로 구성된다 = 3개의 TCB가 존재한다
- TCB는 커널에 의해 생성/관리됨
- 운영체제 커널이 스케줄링을 통해 한개의 tcb를 선택하고 cpu에게 tcb에 저장된 주소에서 스레드 코드를 실행하도록 함
일반적인 함수는 다른 함수에 의해 호출되어 실행되지만, 스레드 함수의 코드는 커널에 의해 직접 cpu가 실행하도록 제어된다
멀티스레딩과 concurrency, parellelism concurrency(동시성, 동시처리)
- 스레드가 입출력을 기다리는 동안 cpu가 다른 스레드를 실행하거나 스레드에게 할당된 타임 슬라이스가 다할때 cpu가 다른 스레드에게 할당하야 실행시키는 방식 parellelism(병렬성)
- 2개이상의 스레드가 서로 다른 cpu에서 동시에 실행되는 것
3. 스레드 주소 공간과 컨텍스트
3.1 스레드 주소공간
스레드의 주소공간(thread address space)은 스레드가 실행 중에 사용하는 메모리 공간으로 스레드의 코드, 데이터, 힙, 스택 영역이며 이들은 모두 프로세스의 주소 공간에 형성된다
스레드 주소공간은 스레드가 사적으로 사용하는 공간과 스레드 사이 공유 공간으로 나뉜다
- 스레드 사적 공간 - 스레드 스택과 스레드 로컬 스토리지
- 스레드 공유 공간 - 프로세스의 코드, 데이터(로컬 스토리지 제외), 힙 영역
스레드마다 별도의 스레드 스택이 주어지며 데이터를 저장할 별도의 데이터 공간이 주어진다
- 스레드 코드 영역
- 프로세스 코드 영역 내에 존재
- 스레드가 호출하여 프로세스 코드 영역에 적재된 모든 함수 사용
- 스레드 데이터 영역
- 스레드 로컬 스토리지 : 자신만 사용할 수 있는 변수를 선언하는 공간
- 프로세스에서 선언된 모든 전역 변수는 모든 스레드에 의해 공유됨 : 상호 데이터 공유 공간
- 스레드 힙 영역
- 프로세스 힙은 프로세스에 속한 모든 스레드들이 동적 할당받는 힙 공간으로 공유
- 한 스레드가 할당받은 동적 메모리는 주소만 알면 다른스레드가 접근 가능
- 데이터를 주고받는 통신 장소
- 스레드 스택 영역
- 스레드가 사용자 모드에서 호출한 함수들의 매개변수들과 지역변수 등을 독립적으로 저장하기 위한 공간(스레드의 사적 공간)
- 스레드가 생성될 때 프로세스에게 할당된 커널 스택에서 각 스레드마다 고유한 스택에 할당
- 스레드가 시스템 호출을 통해 커널 모드로 진입할 때마다 사용되며 커널 모드에 있는 내내 커널 내에서 함수 호출 등에 사용됨
3.2 스레드의 주소 공간 확인
함수 코드와 함수의 변수들을 분리하여 다룸 → 두 스레드가 동일한 코드를 실행하더라도 함수의 매개변수와 지역변수들은 스레드마다 별도의 스택에 저장되기 때문에 문제가 발생하지 않음
3.3 스레드 상태와 스레드 운용(operation)
스레드의 상태변화
- 준비상태(ready) - 스레드가 스케줄을 기다리는 상태
- 실행상태(running) - 스레드가 현재 cpu에 의해 실행되고 있는 상태
- 블록상태(blocked) - 스레드가 입출력을 요청하거나 sleep()과 같은 시스템 호출로 커널에 의해 중단된 상태
- 종료상태(terminated) - 스레드가 종료한 상태
스레드 상태는 TCB(스레드 제어 블록)에 저장됨 스레드에 대한 연산 혹은 운용은 스레드 생성, 종료, 조인, 양보등이 있으며 이들은 스레드를 구현하는 커널이나 스레드 라이브러리에 의해 이루어짐
스레드 생성(thread creation)
프로세스 생성시 운영체제가 자동으로 main 스레드 생성 스레드에 의해 생성된 스레드는 부모-자식 스레드로 불림 부모 스레드는 자식 스레드에 대한 스레드 id를 가지고 자식 스레드 제어
스레드 생성과정 TCB 구조체를 만든 후 스레드에게 ID 부여 → 스레드가 실행을 시작할 코드의 주소를 TCB의 PC에 기록 → 스레드 사용자 스택 할당 후 주소를 TCB의 SP에 저장 → 스레드 상태를 ready로 하고 스레드를 준비 리스트에 넣음 → TCB를 프로세스의 PCB와 다른 TCB에 연결
스레드 종료(thread termination)
프로세스 종료 → main 스레드가 종료하는 경우 & exit() 시스템 호출을 부르는 경우 & 모든 스레드가 종료되는 경우 스레드 종료 → pthread_exit() 함수 호출
- tcb가 시스템에서 제거되고 tcb가 연결된 링크들이 해제되는 것
- 스레드 종료 후에도 스레드 코드 등 스레드에게 할당된 영역은 프로세스 영역 내 그대로 유지
- 프로세스가 종료할때까지 다른 스레드에게 할당할 수 없음
- 스레드 스택과 tls 영역은 다른 스레드가 생성될 때 할당
- 한 스레드가 다른 스레드를 강제 종료하는 방법은 x
스레드 조인(thread join)
스레드가 다른 스레드의 종료를 기다리는 행위
스레드 번호만 알면 다른 스레드 조인 가능
주로 부모스레드가 자식 스레드를 생성하여 작업시키고 기다릴때 사용
스레드 양보(thread yield)
실행중인 스레드가 다른 스레드에게 cpu를 양보하기 위해 스스로 실행을 중단하는 행위
3.4 스레드 컨텍스트와 스레드 제어 블록(TCB)
스레드 컨텍스트
스레드가 현재 실행중인 일체의 상황 CPU내 레지스터들과 메모리에 담겨있음 메모리 : 코드와 데이터 스택 : 현재 실행중인 스레드 코드 주소 sp 레지스터 : 스레드 스택의 top 주소 데이터 레지스터 : 실행 결과나 사용될 데이터 상태 레지스터 : cpu 상태 정보와 프로그램에 의해 설정된 제어 정보
스레드 컨텍스트는 CPU가 스레드를 실행되고 있을 때 cpu의 레지스터 값들
스레드 제어 블록(tcb, thread control block)
커널 내 스레드마다 스레드 제어블록이라는 구조체를 만들어 관리
스레드가 생성될 때 만들어지고 종료되면 제거
운영체제는 프로세스와 스레드를 함께 관리
pcb와 프로세스 내 속한 모든 스레드의 tcb들을 링크드 리스트로 연결하여 관리
프로세스들은 스레드들이 생기고 활동하는 자원의 컨테이너로서 운영체제는 프로세스를 스케줄링 단위가 아니라 스레드들을 위한 자원의 할당 단위로 다룸 커널이 실행 단위로 인식하는 스레드 실체는 TCB 이다
준비 리스트와 블록 리스트
커널은 준비상태의 스레드와 블록 상태의 스레드 관리를 위해 준비 리스트와 블록 리스트의 링크드 리스트로 tcb를 연결하여 관리
준비 리스트의 tcb중 하나를 선택
실행중인 스레드가 양보하거나 cpu 타임 슬라이스를 다 소모한 경우 준비 리스트에 삽입
블록 상태가 되면 블록 리스트에 삽입
3.5 스레드 컨텍스트 스위칭
현재 cpu가 실행중인 스레드를 중단시키고 cpu에게 새 스레드를 실행시키는 과정
스케줄러 코드를 이용하여 새로 실행시킬 스레드를 선택하고(스케줄링)
현재 스레드의 cpu레지스터 값을 tcb에 저장하고
선택된 스레드의 tcb로부터 스레드 컨텍스트를 cpu에 적대하여 새 스레드를 실행 (컨텍스트 스위칭)
cpu 자원을 한 스레드에서 다른 스레드로 옮기는 작업
스레드 스위칭이 발생하는 경우
- 스레드가 자발적으로 다른 스레드에게 양보하는 경우
- yield() 시스템 호출 or sleep()이나 wait() 등의 시스템 호출을 불러 컨텍스트 스위칭 되는 경우
- 스레드가 I/O 작업을 요청하는 시스템 호출 시 블록되는 경우
- 스레드가 타임 슬라이스를 소진한 경우
- I/O 장치로부터 인터럽트가 걸린 경우
스레드 스위칭이 이루어지는 위치
시스템 호출을 처리하거나 인터럽트 서비스 루틴의 실행 도중 커널 코드에서 이루어짐
스레드 스위칭 과정
- cpu 레지스터 저장 및 복귀
- 현재 실행중인 스레드 a의 컨텍스트를 tcb-a에 저장
- tcb-b에 저장된 스레드 b의 컨텍스트를 cpu에 적재
- 커널 정보 수정 - 상태 정보와 cpu 사용 시간등을 수정하고 tcb-a를 블록 리스트로 옮기고 tcb-b를 준비 리스트에서 분리
3.6 컨텍스트 스위칭의 오버헤드
컨텍스트 스위칭에 걸리는 시간이 큼 → 컴퓨터의 처리율이 떨어짐
동일한 프로세스의 다른 스레드로 스위칭 하는 경우
- 컨텍스트 저장 및 복귀시간
- tcb리스트 조작 시간
- 캐시 플러스 및 채우기 시간
- 캐시 플러시(cache flush) : 현재 cpu 캐시에 담겨있는 스레드 코드와 데이터를 지우거나 변경된 데이터를 메모리로 복사
다른 프로세스의 스레드로 스위칭 되는 경우
주소 공간이 완전히 바뀜
- 메모리 관련 오버헤드
- MMU 장치 내에 들어있는 이전 맵 테이블을 제거하고 새로운 프로세스 맵 테이블 적재
- cpu내 현재 프로세스의 tlb를 모두 비우고 cpu에 새 프로세스 tlb를 채우는 작업
- 추가적인 캐시 오버헤드
- cpu 캐시에 담긴 프로세스 코드와 데이터 무효화
스레드 스위칭 오버헤드 줄이기
- 프로세스를 특정 cpu 코어에 배치하여 cpu 코어가 여러 프로세스에 걸쳐 스레드를 실행하지 않도록 하는 방법
- cpu에 스레드별로 레지스터셋을 따로 두어 컨텍스트 스위칭 시 현재 실행중인 스레드의 cpu레지스터들을 tcb에 저장하지 않는 방법 사용
4. 커널 레벨 스레드와 사용자 레벨 스레드
4.1 커널 레벨 스레드와 사용자 레벨 스레드
스레드 스케줄링 : TCB를 실행 단위로 하여 시스템 내 tcb들 중 하나를 선택하는 것
스레드 스케줄링 주체
- 커널 레벨 스레드 - 커널에 의해 스케줄링되는 스레드
- 사용자 레벨 스레드 - 스레드 라이브러리에 의해 스케줄링 되는 스레드
커널 레벨 스레드
TCB가 커널에 의해 커널 공간에 만들어지고 커널에 의해 스케줄되는 스레드
시스템 호출을 통해서만 만들어지고, 커널에 의해 그 존재가 인지되고, 커널에 의해 스케줄링 됨
시스템 호출을 통해 스레드를 만들면 tcb가 커널 공간에 만들어지고 tcb에 기록된 스레드 코드의 주소는 응용프록 램의 코드를 가리킴 커널 스케줄러에 의해 스케줄링되면 cpu는 응용프로그램에 작성된 사용자 코드를 실행함
순수 커널 레벨 스레드 : 부팅할때부터 커널 공간에서 실행되도록 작성된 커널 레벨 스레드
사용자 레벨 스레드
스레드 라이브러리에 의해 사용자 공간에 생성되고, 관리되고, 스케줄되는 스레드
응용프로그램은 스레드 라이브러리의 함수를 호출하여 스레드를 생성하고, 스레드 라이브러리는 생성한 tcb를 사용자 공간에 저장함
스레드 라이브러리 → 사용자 레벨 스레드가 실행되는 환경 역할
4.2 커널 레벨 스레드와 사용자 레벨 스레드 사례
순수 커널 레벨 스레드
- 커널을 돕기 위해 만든 스레드
- 커널 모드에서만 실행되고 사용자와 대화하지 않으며 백그라운드에서 실행
커널 레벨 스레드
- 커널이 스케줄링 할 수 있는 TCB를 커널 공간에 만든다
- 커널에 만들어진 TCB들을 대상으로 커널에 의해 스케줄링 되는 스레드
사용자 레벨 스레드
- 프로세스 사용자 주소공간에 응용프로그램과 스레드 라이브러리가 함께 적재
스레드의 스케줄링 및 실행
cpu에 2개의 코어 → 코어당 1개씩 2개의 스레드가 병렬적으로 실행 tcb1~4까지 4개의 커널 레벨 스레드만 대상으로 스케줄링 사용자 레벨 스레드의 스케줄링은 스레드 라이브러리의 스케줄링 함수가 다른 사용자 레벨 스레드의 주소로 점프하는 식으로 이루어짐
4.3 사용자 레벨 스레드의 유용성
커널의 도움을 받지 않고 스레드를 만들고 스케줄링 할 수 있는 스레드 라이브러리 개발 → 사용자 레벨 스레드 도입 → 쉽게 멀티스레드 응용프로그램 작성이 가능해짐
4.4 사용자 레벨 스레드와 커널 레벨 스레드 비교
4.5 커널 레벨 스레드와 사용자 레벨 스레드의 장단점
컨텍스트 스위칭과 스레드 관리
사용자 레벨 스레드 > 커널 레벨 스레드
- 커널 레벨 스레드
- 커널 공간 내에서 이루어짐
- tcb 리스트 조작 과정
- tlb 내용 교체 오버헤드 발생
- 사용자 레벨 스레드
- 커널 진입 부담 x
- 저장되거나 복귀되는 데이터 양이 적어 시간이 적음
- 스레드 생성 시간도 적음
이식성 및 활용성
사용자 레벨 스레드 > 커널 레벨 스레드
- 스레드 라이브러리에 의해 관리되므로 운영체제에 종속적이지 않음
- 멀티스레드를 지원하지 않는 운영체제에서도 스레드 라이브러리를 이용하면 응용프로그램 작성 가능
실행 블록킹
사용자 레벨 스레드 < 커널 레벨 스레드
- 사용자 레벨 스레드로 작성된 멀티스레드 응용프로그램
- 블록상태가 될 때 응용프로그램 내 다른 모든 사용자 레벨 스레드가 실행될 수 없음
- 커널 레벨 스레드로 작성된 멀티스레드 응용 프로그램
- 임의의 커널 레벨 스레드가 블록되더라도 다른 커널 레벨 스레드가 스케줄링되어 실행 가능
병렬성
사용자 레벨 스레드 < 커널 레벨 스레드 사용자 레벨 스레드 : 하나의 cpu코어에서 스레드 라이브러리에 의해 번갈아 실행, 병렬적으로 실행 x
5. 멀티스레드 구현
5.1 배경
응용프로그램에서 생성된 사용자 레벨 스레드의 코드가 cpu에 의해 실행되려면 커널에 의해 스케줄되어야 함
- N:1 매핑
- 1:1 매핑
- N:M 매핑
5.2 N:1 매핑
하나의 응용프로그램에 속한 모든 사용자 스레드를 하나의 커널 스레드로 매핑하는 개념
커널이 현재 어떤 스레드 코드가 실행되는지 알지 못함
장점
- 스레드 라이브러리에 의해 사용자 공간에서 이루어져 멀티스레드 응용프로그램이 실행되는 속도가 빠름
단점
- 사용자 스레드 중 하나에게만 cpu코어가 할당되므로 멀티코어 cpu를 가진 현대의 컴퓨터에서 개발자가 의도했던 멀티스레드의 병렬성을 얻을 수 없음
- 한 사용자 스레드가 시스템 호출을 시행하여 블록상태가 되면 나머지도 실행할 수 없어 응용프로그램이 중단됨
5.3 1:1 매핑
사용자 레벨 스레드 하나당 커널에 의해 스케줄 가능한 엔터티 (TCB) 하나를 연계시킴 커널이 스케줄링을 통해 tcb를 선택하면 cpu에게 이 tcb에 연결된 사용자 레벨 스레드 코드를 실행하도록 하는 기법
응용 프로그램에서 만든 2개의 스레드가 서로 다른 코어에서 동시에 실행됨
장점
- 구현하기 쉬움
- 여러개의 cpu 코어에서 동시에 사용자 레벨 스레드가 실행됨 → 높은 병렬성 제공
- 사용자 레벨 스레드중 하나가 시스템 호출 중 블록상태가 되어도 다른 스레드는 여전히 스케줄링 가능
단점
- 운영체제 비용 부담이 큼
- 커널모드 진입 횟수가 많아짐
- 스케줄에 다른 시간부담 많아짐
- 커널의 부담이 매우 큼 1!
5.4 N:M 매핑
N개의 스레드들을 M개의 커널 레벨 스레드에 연계시키는 방법 커널 스케줄링을 통해 커널 레벨 스레드 중 하나 선택 → 사용자 레벨 스레드 중 하나 선택 1:1 매핑과 N:1 매핑 단점 보완, 매핑 구현이 복잡함
장점
- 1:1 매핑에 비해 커널 레벨 스레드의 개수가 적어 커널 부담이 줄어듬
단점
- 매핑과 스케줄링 과정이 복잡하여 현대 운영체제에서는 거의 사용 x
6. 멀티스레딩 이슈
6.1 프로세스와 스레드 리뷰
- 프로세스는 여러 스레드들의 코드와 데이터, 힙, 스택이 생성되고 실행되는 주소공간이며 여유공간
- 프로세스는 운영체제가 응용프로그램을 적재하는 단위, 실행단위는 스레드
- PCB에 저장된 정보를 환경 컨텍스트라고 하고 TCB에 저장된 정보를 실행 컨텍스트라고 함
- 동일한 프로세스 내 속한 스레드 사이의 컨텍스트 스위칭은 서로 다른 프로세스에 걸쳐 있는 스레드들 사이 컨텍스트 스위칭보다 빠름
- 프로세스에 속한 모든 스레드가 종료할 대 프로세스도 종료, exit() 시스템 호출 실행시 모든 스레드 종료
6.2 멀티스레딩으로 응용프로그램을 작성하는 장점
높은 실행 성능
- 입출력작업과 cpu 사용 시간이 많은 계산 중심 작업을 각각 스레드로 만들면 스레드들이 동시에 처리되어 cpu 활용률이 높아짐
- 멀티코어 cpu를 가진 컴퓨터에서 스레드들이 여러 코어에서 병렬 실행되어 응용프로그램의 실행 시간 단축
사용자에 대한 우수한 응답성
- 응용프로그램을 멀티스레드로 잓어하면 한 스레드가 블록되어도 다른 스레드들은 스케줄링되어 실행되기때문에 전체블록되는 일은 일어나지 않음
서버 프로그램의 우수한 응답성
- 접근하는 각 사용자마다 스레드를 할당하여 서비스함으로써 동시에 접근하는 많은 사용자들에게 높은 응답성을 줄 수 있음
시스템 자원 사용의 효율성
- 스레드는 프로세스에 비해 생성하고 유지하는데 메모리나 자원이 적게 사용됨
응용프로그램 구조의 단순화
- 응용 프로그램의 구조를 단순화 할 수 있음
- 각 작업을 함수 수준의 간단한 루틴으로 작성 가능, 응용프로그램의 확장이나 변환을 용이하게 함
작성하기 쉽고 효율적인 통신
- 스레드들이 프로세스의 주소공간을 공유하기 때문에 스레드 사이의 통신은 간단하고 코딩하기 편리함
- 데이터 공유시 프로세스의 전역변수나 동적 할당 메모리를 사용하면 공유 속도도 빠르고 데이터양에의한 문제도 발생하지 않음
6.3 멀티스레딩에 있어 주의점
- 프로세스에 여러개의 스레드가 있을 때 한 프로세스가 fork() 시스템 호출을 이용하여 자식 프로세스를 생성하는 경우
- fork후 자식 프로세스에는 main 스레드만 유일하게 실행됨
- 스레드가 exec() 시스템 호출을 실행하는 경우
- 스레드 사이의 동기화 문제
- 여러 스레드가 공유 데이터에 동시 접근하면 공유 데이터를 훼손시킬 수 있음