Java ‐ 프로세스와 쓰레드 - thought-corner/Backend-PlayGround GitHub Wiki
멀티태스킹과 멀티프로세싱
- 멀티 태스킹(Multi Tasking)
- 하나의 컴퓨터 시스템이 동시에 여러 작업을 수행하는 능력을 멀티 태스킹이라고 한다.
- 프로그램 A의 코드 1을 수행하고 바로 이어 프로그램 B의 코드 1을 수행한다.
- 찰나의 시간에 바로바로 작업을 이어 받아 마치 동시에 실행되는 것처럼 보이는 이 기법을 시분할(Time Sharing) 기법이라고 한다.
❗스케줄링(Scheduling)
- CPU에 어떤 프로그램이 얼마만큼 실행될지는 운영체제가 결정하는데 이것을 스케줄링이라고 한다.
- 단순히 시간으로만 작업을 분할하는 것이 아니라 CPU를 최대한 활용할 수 있는 다양한 우선순위와 최적화 기법을 제공한다.
- 운영체제가 스케줄링을 수행하고 CPU를 최대한 사용하면서 작업이 골고루 수행될 수 있게 최적화한다.
- 멀티 프로세싱(Multi Processing)
- 둘 이상의 코어를 사용하여 여러 작업을 동시에 처리하는 기법을 말한다.
프로세스와 쓰레드
- 운영체제 안에서 실행 중인 프로그램을 프로세스라고 한다.
- 프로세스는 실행 중인 프로그램의 인스턴스이다.
- 각 프로세스는 별도의 메모리 공간을 갖고 있어 서로 간섭하지 않는다. 그리고 프로세스가 서로의 메모리에 접근할 수 없다.
- 프로세스는 서로 격리되어 있기 때문에 하나의 프로세스가 충돌한다고 하더라도 다른 프로세스에는 영향을 미치지 않는다.
- 쉽게 이야기해서 특정 프로세스에 문제가 발생하면 해당 프로세스만 종료되고 다른 프로세스에 영향을 주지 않는다.
- 프로세스의 메모리 구성
- 코드 섹션 : 실행할 프로그램 코드가 저장되는 부분
- 데이터 섹션 : 전역 변수 및 정적 변수가 저장되는 부분
- 힙 : 동적으로 할당되는 메모리 영역
- 스택 : 지역 변수, 메서드 호출 내역 등이 저장되는 부분
- 프로세스는 하나 이상의 쓰레드를 반드시 포함한다.
- 쓰레드는 프로세스 내에서 실행되는 작업의 단위이다. 한 프로세스 내에는 여러 쓰레드가 존재할 수 있으며, 이들은 프로세스가 제공하는 동일한 메모리 공간을 공유한다.
- 쓰레드는 프로세스보다 단순하기에 생성 및 관리가 단순하고 가볍다.
- 쓰레드 메모리 구성
- 공유 메모리 : 같은 프로세스의 코드 섹션, 데이터 섹션, 힙은 프로세스 안의 모든 쓰레드가 공유한다.
- 개별 스택 : 각 쓰레드는 자신만의 스택을 가진다.
컨텍스트 스위칭
- 멀티 태스킹 작업의 경우 찰나의 시간에 바로바로 작업을 이어 받아 동시에 실행하는 것처럼 보이게 된다.
- 이 찰나의 시간에 바로바로 작업을 가져오는 과정에서 어느 시점까지 처리를 했는지 기억을 해야한다.
- 쓰레드 A를 멈추는 시점에 CPU에서 사용하던 이런 값들을 메모리에 저장해두어야 한다. 그리고 이후에 쓰레드 A를 다시 실행할 때, 이 값들을 CPU에 다시 불러와야 한다.
- 이 과정을 컨텍스트 스위칭(문맥 교환, Context Switching)이라고 한다.
- 쓰레드가 하는 작업은 크게 2가지로 나눌 수 있다.
- CPU Bound : CPU의 연산 능력을 많이 요구하는 작업을 말한다. 주로 계산, 데이터 처리, 알고리즘 실행 등 CPU 처리 속도가 작업 완료 시간을 결정하는 경우이다.
- I/O Bound : 디스크, 네트워크, 파일 시스템 등과 같은 입출력 작업을 많이 요구하는 작업을 말한다. 이러한 작업은 I/O 작업이 완료될 때까지 대기 시간이 많이 발생하며, CPU는 상대적으로 유휴 상태에 있는 경우가 많다. 주로 데이터베이스 쿼리 처리, 파일 읽기/쓰기, 네트워크 통신, 사용자 입출력이 있다.
- 프로세스 또는 쓰레드의 상태를 저장하여 나중에 복원하고 실행을 재개할 수 있도록 한 다음, 이전에 저장된 다른 상태를 복원하는 과정을 말한다.
- 이를 통해 여러 프로세스가 CPU를 공유할 수 있으며, 멀티 프로그래밍 또는 멀티태스킹 운영체제의 필수적인 기능이다.
1. PCB/TCB와 상태의 저장
- PCB(Process Control Block): 프로세스 단위의 스위칭 시 CPU 레지스터 값, PC(Program Counter), 스택 포인터, 메모리 관리 정보 등을 저장한다.
- TCB(Thread Control Block): 쓰레드 단위의 스위칭 시 사용되며, 프로세스 내의 자원을 공유하면서 쓰레드별 독립적인 스택과 레지스터 정보만 교체하므로 PCB 스위칭보다 가볍다.
2. 상세 동작 과정
- 인터럽트/시스템 콜 발생 : OS가 CPU 제어권을 획득한다.
- 현재 상태 저장 : 현재 실행 중인 프로세스(P1)의 문맥을 해당 PCB에 저장한다.
- 스케줄러 선택 : 다음 실행할 프로세스(P2)를 스케줄링 알고리즘에 따라 선택한다.
- 상태 복원 : 선택된 프로세스(P2)의 PCB에서 이전 상태를 CPU 레지스터에 로드한다.
- 실행 재개 : 복원된 PC(Program Counter) 값부터 실행을 시작한다.
3. 오버헤드와 성능 영향
- 컨텍스트 스위칭은 순수하게 관리를 위한 작업이므로 CPU 자원을 소모하는 오버헤드가 발생한다.
- 캐시 플러시(Cache Flush) : 새로운 프로세스가 실행되면 기존 CPU 캐시에 있던 데이터들이 무효화(Invalidation)되어, 초기 실행 속도가 떨어지는 '캐시 미스'가 빈번하게 발생한다.
- TLB(Translation Lookaside Buffer) 교체 : 가상 메모리 주소를 물리 주소로 변환하는 TLB 정보가 프로세스마다 다르기 때문에, 프로세스 스위칭 시 이 정보가 갱신되어야 한다.
4. 프로세스 vs 쓰레드 스위칭
- 프로세스 스위칭: 가상 메모리 주소 공간이 완전히 다르므로 TLB와 캐시를 대거 교체해야 하여 오버헤드가 크다.
- 쓰레드 스위칭: 같은 프로세스 내의 쓰레드들은 데이터/코드 영역을 공유하므로 주소 공간을 바꿀 필요가 없어 훨씬 빠르다.