운영체제 (OS) - Chapter 04
● Chapter 04의 목표
- 다중 프로그램 운영 체제기반의 CPU 스케줄링에 대해 설명
- 멀티스레드 컴퓨터 시스템의 작동에 필수적인 CPU 활용의 기본 단위인 쓰레드에 대해 설명
- Pthreads(POSIX 스레드), Windows, Java를 포함한 다양한 환경에서 쓰레드 관리를 위한 API에 대해 설명
- 암시적 스레딩을 지원하는 다양한 방법 지원하는 몇몇 쓰레드 전략들에 대해 설명
- 멀티스레드 프로그래밍에서 흔히 발생하는 문제들에 대해 설명
- Windows 및 Linux와 같은 운영 체제가 쓰레드에 대해 지원하는 서비스들에 대해 설명

● Motivation
- 대부분의 현대 애클리케이션들은 멀티스레드로 구성됨
- 쓰레드는 애플리케이션 안에서 실행됨
- 애플리케이션에서 다중작업은 각 작업들을 별도의 쓰레드들로 나뉘어 실행됨
(ex -화면 업데이트, 데이터 가져오기, 맞춤법 검사, 네트워크 요청등)
- 프로세스로 만든 것들은 무겁지만 쓰레드를 활용해 만든 것은 가벼움
- 코드를 간소화 시키고 효율을 늘릴 수 있음
- 커널들은 일발적으로 멀티 쓰레드로 구성됨
[쓰레드 (Thread)]
- CPU를 사용하는 가장 기본적인 Unit
- 하나의 실행 흐름을 구성
- Application내에서 동작함
- kernal들은 일반적으로 multi Thread를 가짐
- Thread 별로 각각의 program counter를 가짐

● Multithreaded server Architecture
1) 클라이언트가 서버에게 요청을 보냄
2) 클라이언트 요청을 처리하기 위해 서버가 새로운 쓰레드를 생성함
3) 서버는 추가적인 클라이언트 요청들을 받기 위해 대기상태를 재개함

● Multithreaded의 장점
- 응답성 ( Responsiveness ) : 프로세스 일부가 블록이 되는 경우에도 계속 실행할 수 있으며, 특히 사용자 인터페이스에서 중요함
- 자원 공유 (Resource Shariing) : 쓰레드는 프로세스의 자원을 공유하며, 공유 메모리나 메시지 전달보다 더 쉽게 자원을 사용할 수 있음
- 경제성 (Economy) : 프로세스로 만든 것보다 쓰레드로 만든게 더 저렴하며 쓰레드들 스위칭 할 때 드는 비용이 프로세스의 Context Switching 비용보다 저렴함
- 확장성 (Scalability) : 멀피프로세스 구조의 장점을 그대로 가질 수 있음

● Multicore Programming
- 멀피코어나 멀티 프로세스 시스템들은 프로그래머들에게 아래와 같은 난관을 제공함
- 작업분배 (Dividing activity)
- 균형(Balance)
- 데이터 분할 (Data splitting)
- 데이터 의존성 (Data dependency)
- 테스트 및 디버깅 (Testing and debug)
- 병렬성은 한 시스템이 동시에 한개 이상의 작업을 수행할 수 있다는 것을 암시함
- 동시성은 하나 이상의 작업을 지원해줌 ( 단일 프로세서/코어, 동시성을 제공하는 스케쥴러 )

● Multicore Programming
[ Parallelism의 종류 ]
- 데이터 병렬성 (Data parallelism - 동일한 데이터를 여러코어에 같은 작업으로 분배해줌
- 작업 병렬성 (Task parallelism) - 여러 코어에 개별작업을 처리하는 쓰레드들을 분배해줌
- 쓰레드의 수가 증가함에 따라 쓰레딩에 대한 아키텍쳐 지원도 증가함
- CPU는 코어들 뿐만 아니라 하드웨어 쓰레드들까지 가지고 있음

● Concurrency Vs Parallelism

● Single and Multithreaded Process

● Ardam's Law
Speed Up <= 1/ (s+(1-s)/n)
위의 예제에선 S = 1/4, N=2 이므로 1/( 4분의1 + 4분의3 / 2) 이므로 1/ (4분의1 + 8분의 3 ) 이고, 답은 1/(8분의5) 즉, 5분의8인 1.6이다

● User Threads and Kernel Threads
[Thread 종류]
- User Thread: 유저수준에서 관리하는 thread
- Kernel Thread: 커널에 의해서 관리되는 thread
커널에서는 프로세스를 대부분 관리 -> user 쓰레드는 모름
(우리 입장에선 굳이 user thread와 kernel thread를 나눠서 보진 않음)

● Multithreading Models - Many-to-One
[Many-to-One]
- 여러개의 user thread가 하나의 kernenl thread에 매핑됨
- 동시에 thread들을 실행하는 것이 어려움
- user thread들 중 하나라도 blocking 문제가 발생하면 모든 user thread에도 blocking이 발생

● Multithreading Models - One-to-One
[One-to-One]
- user thread와 kernel thread가 일대일로 매핑됨
- many-to-one보다 더 concurrency(동시성)가 좋음
- OS가 감당할 수 있을 정도로 thread를 만들도록 제한됨

● Multithreading Models - Many-to-Many
[Many-to-Many]
- 여러개의 user thread가 여러개의 kernel thread에 매핑됨
- user thread의 개수와 kernel thread의 수가 같을 필요는 없음
- 실질적으로 user thread가 실행될 kernel thread를 적절하게 매핑시켜줘야함

● Multithreading Models - Two-level Model
[Two-level Model]
- Many-to-Many와 유사한 모델, 일부 user thread가 kernel thread와 섞일 수 있음 -> One to One + Many to Many가 합쳐진 모델

● Thread Libraries
- 쓰레드 라이브러리는 프로그래머에게 쓰레드를 생성하고 관리하는 API를 제공해줌
[ 쓰레드 라이브러리의 실행 유형들 ]
- 라이브러리 전체가 User 공간에 있는 경우
- OS에서 지원해주는 Kernel 수준의 라이브러리

● Pthread
- Pthreads는 User 수준이나 Kernel 수준에서 제공될 수 있음
- POSIX (IEEE 1003.1c) 로 스레드 생성 및 암호화 API를 제공
- 구현(Implementation)이 아닌 사양(Specification)을 제공
- API는 쓰레드 라이브러리의 특정한 행동을 구체화하고, 구현은 라이브러리의 라이브러리 개발까지를 구체화한다

● Java Thread
- JVM에 의해 Java Thread가 관리됨
- 일반적으로 기본적인 OS의 쓰레드 모델들을 사용하여 구현됨


● Java Cancellation
- Thread 작업이 완료되기 전에 종료시키는 것
- 취소된 Thread는 target Thread가 될 수 있음
- Asynchronous cancellation는 target thread를 즉시 종료시킴 (어느시점에서든 취소 요청이 들어오면 취소시킴)
- Deferred cancellation는 target thread를 유예기간을 두고 종료 (취소요청이 왔을 때 바로취소하는게 아니라 지연시켰다가 취소함 - 중단되서는 안되는 task가 있는 경우)

● Thread-Local Storage
- Thread-Local Storage(TLS)는 각 쓰레드가 각자 데이터의 사본을 가지고 있는 것을 허용함
- 쓰레드 생성을 제어할 수 없을 때 유용하게 쓰임
- 일반적인 지역변수와는 다름
- 전역변수와 비슷함
[ Thread-Local Storage(TLS)와 local variable의 차이점 ]
-local variables은 오직 해당 함수내에서만 선언되지만, TLS는 함수 외부에서도 접근가능
but, TLS는 전역변수와는 다른데, 전역변수는 다른 Thread에서 사용가능하지만 TLS는 해당 Thread에서만 사용가능함

● Scheduler Activations
- Many-to-Many나 Two-level 모델을 사용하는 경우, kernel thread를 user thread에 얼만큼 할당시킬지에 대한 커뮤니케이션이 필요함
- 특히 LightWeight Process(LWP)를 사용하기도 함. LWP는 가상 프로세서처럼 사용되며, 사용자 스레드가 실행될 수 있도록 스케줄할 수 있음.
- 스케줄러 활성화: 커널에서 스레드 라이브러리의 upcall handler로 통신 메커니즘을 제공함. 해당 커뮤니케이션으로 애플리케이션은 적절한 수의 커널 스레드를 유지할 수 있음.
user thread와 kernel thread는 현재수준에선 구분하지 않고 thread가 새로 생겼구나 하면됨.