배경
- 프로그램 안에서도 해야하는 작업들이 다 다름.
이를 하나하나 프로세스로 관리하려면 복잡 => 프로그램에 실행할 수 있는 흐름이 여러개가 있으면 어떨까??
Thread란
- 프로세스보다 세분화된 Execution Unit
- 프로세스 내의 실행흐름을 의미
- 프로세스에서 할 작업을 여러개로 나눈후 각각을 쓰레드화하면 병렬적으로 빨리 작업완수 가능
Cooperative 프로세스와의 차이점
- Cooperative 프로세스는 서로 다른 프로세스라 서로 얘기할때 IPC가 필요 -> 비용 많이듬
- 쓰레드는 이미 같은 주소 안에 있으니 IPC가 필요없음
- 쓰레드는 context switching 비용도 줄일 수 있음
쓰레드와 CPU
프로세스와 쓰레드
프로세스
- 하나의 쓰레드와 같은 실행흐름
- 프로세스 메모리는 각각 독립적이라 서로 접근 어려움
- 프로세스 간에 Switch 비용이 큼
쓰레드
프로세스의 코드 영역과 데이터 영역을 쓰레드간에 공유
=> IPC가 필요없음. shared 메모리 느낌
- IPC 비용 필요없고, 스위치 비용도 백업과 복원의 양이 적음으로 얼마 안듬. 굳
쓰레드의 구성요소
- 쓰레드 ID(쓰레드 식별자)
- 실행과 관련된 자료구조(program counter)
- 레지스터 set(CPU의 레지스터 값들
- 스택
쓰레드가 공유하는것
-코드
-데이터
-파일
멀티쓰레드 장점
Responsiveness
- 시간이 걸리는 작업을 해도, 다른 쓰레드들은 실행되고 있기 때문에 유저에게 Interactive한 느낌줌(ex 로딩 게이지 바 UI)
Resource Sharing
- 쓰레드들 간에는 프로세스의 메모리와 다른 자원 공유
Economy
- 프로세스 fork 해서 생성하는거보다 쪼꼬미 쓰레드 만드는게 저렴함
Scalability(확장성)
유저 쓰레드
- 소프트웨어 쓰레드
- 커널 영역에서 지원되며 일반적으로 유저 레벨의 라이브러리로 구현됨(ex 자바 쓰레드)
- 라이브러리에서 쓰레드를 생성, 스케줄링 관리까지 해줌
장점
- 동일한 메모리 영역에서 쓰레드 생성, 관리되서 속도 빨라
단점
- 여러개의 유저 쓰레드 중에서 하나의 쓰레드라도 시스템콜에 의해 Block 되면 나머지 쓰레드들도 다 Block됨. (하나 실수하면 나머지 애들 process 취급당해서 쓰레드 끝 = 병렬성이 미완성)
커널 쓰레드
- 운영체제에서 쓰레드를 지원
- 커널에서 쓰레드 생성, 스케줄링 관리해줌
장점
- OS가 쓰레드를 알고있어서 한개가 Block 되도 나머지 쓰레드들은 데미지 없음 = 병렬성
- 멀티프로세서 환경에서 커널이 여러개의 쓰레드를 다른 프로세서에 할당할 수 있음.
단점
- 아무래도 커널에서 관리 생성 하다보니 유저 쓰레드보다 느림
두 쓰레드를 OS에서 어떻게 관리할까?
Many-to-one
- 쓰레드 관리는 유저레벨에서 이루어짐
- 여러개의 유저레벨 쓰레드들이 하나의 커널 쓰레드로 매핑됨
한계점
한번에 하나의 쓰레드만 커널에 접근가능
- 하나의 쓰레드가 커널에 접근(시스템콜)하면 나머지 쓰레드는 대기해야 = 병렬성과 거리가 멈
- 여러개 쓰레드가 동시에 시스템 콜 불가
- 커널 입장에서는 하나의 프로세스로 보기 때문에 멀티프로세서여도 여러개 프로세서가 동시 실행 불가능
(대안)One-to-One
-
운영체제에서 유저 쓰레드를 제대로 사용하기 위한 대안.
-
각각의 모든 유저 쓰레드를 각각의 커널 쓰레드에 매핑!
-
쓰레드와 커널이 한 조가 되니까 시스템콜 호출 시 다른 쓰레드들이 Block 되는 문제 해결
-
여러개의 쓰레드를 멀티프로세서에서 동시 실행가능 = 병렬 가능!
한계점
- 커널 쓰레드도 한정적이기 때문에 무한으로 즐길 수 없음
(대안)Many-to-Many
-
Many-to-One 과 One-to-One 의 하이브리드 느낌
-
커널 쓰레드<= 유저 쓰레드 개수로 생성
ex) 유저 쓰레드 4개에 커널 쓰레드 3개 매핑
-
가능한 만큼만 만들기 때문에 One-to-One 보안
-
시스템 콜해도 Block 되는 현상도 해결
쓰레드로 인한 이슈들
프로세스 기반의 운영체제 시스템콜
- 기존 시스템콜은 프로세스 기반으로 작성됨
- 쓰레드 개념 반영함
ex) fork, exec 등의 쓰레드 지원 변화 필요
- 쓰레드 종료문제에 대안 필요 -> 쓰레드는 메모리를 공유하기 때문에 막 강제종료 불가
Creation
fork(프로세스 복사)
- 하나의 프로그램 내의 쓰레드가 fork 하면 모든 쓰레드를 가지고 있는 프로세스를 만들건지? or 아니면 fork 요청한 쓰레드만 복사한 프로세스를 만들건지?
=> 둘다 필요할꺼 같아서 리눅스에서는 2가지 버전 fork 만듬
exec (저장되어있는 프로그램을 프로세스에 붙여넣기)
- fork로 모든 쓰레드 복사한 다음에 exec 하면 쓰레드들은 새로운 프로그램으로 교체됨 => 교체될 애들까지 복사하는건 비효율적
- fork 요청한 쓰레드만이 복사되는게 효율적! but, 모든 쓰레드의 fork 가 필요하기도 하니..
Cancellation 쓰레드 종료 이슈
- ex) 웹서핑 중에 이미지 읽어오다가 중지버튼 눌렀을 경우, 이미지 읽어오는 쓰레드도 중지되야함
- 자원이 쓰레드에게 할당되었을 경우 취소 문제는 os가 신중하게 해제해야함
Thread Pools(쓰레드 재활용)
- 쓰레드 자주 생성되고 제거되는 상황에서, 만드는시간이 더 오래걸릴수 있음.
- 최대한의 쓰레드 수에 대한 제한이 필요
해결 방안
- 쓰레드 풀을 만들어서 프로세스가 새로 실행될때 일정 수만큼의 쓰레드만큼 만든 후에 pool 에 할당
- 새로운 쓰레드가 필요하면 미리 만들어놓은 pool에서 가져오고 작업 끝나면 쓰레드 pool로 수거
- 쓰레드 생성에 따른 시스템 부하를 줄일 수 있음
- 프로세스의 상황을 보고 pool에서 유동적으로 쓰레드 수를 결정함
Thread 간 IPC
- 쓰레드들은 같은 프로세스 안에 메모리를 공유함
- IPC 쓸 필요가 없음ㅎㅎ