스레드 개념 및 구현
프로세스와 쓰레드
프로세스
- 프로세스는 운영체제가 프로그램을 실행하기 위한 정보들을 가진 실제 메모리가 적재된 Instance를 구성한 작업 단위
- 프로세스는 운영체제에 의해 각 메모리 영역을 할당 받음
- 프로세스는 PCB(Process Control Block)을 통해 자신이 실행 할 컨텍스트, 주소 공간, 스케쥴링 정보, 메모리 매핑 테이블 등을 소유
스레드
- 스레드는 CPU가 해당 프로그램을 실행하기 위한 정보와 실행 흐름을 가진 최소한의 작업 단위
- 프로세스의 메모리 영역을 공유하며 각 스레드 별 TCB(Thread Control Block)를 통해 실행 중이던 컨텍스트 정보와 스케쥴링 정보, 스레드가 소속된 프로세스의 PCB 주소 등을 소유
컨텍스트 스위칭
- 앞선 내용과 같이 쓰레드는 프로세스에 비해 컨텍스트 스위칭 비용이 저렴하기 때문에 보다 효율적이라고 함
- 컨텍스트 스위칭이 뭘까?
컨텍스트 스위칭 기본 구조
- 컨텍스트 스위칭은 프로세스가 가진 상태 정보를 제어할 수 있는 PCB(Process Control Block)의 교환으로 이루어짐
- CPU는 한번에 한가지 작업만을 수행가능, CPU 레지스터에 저장된 정보의 사용도 동일
- 그런 CPU가 시분할 시스템에 의해 멀티 프로세싱을 하기 위해선 인터럽트가 발생한 프로세스로 이전에 CPU 레지스터가 가지고 있던 실행 컨텍스트를 저장하고, 앞으로 진행할 프로세스 정보를 PCB에서 읽어와 레지스터에 적재하는 작업이 필요한데 이를 Context Switching(문맥 교환)이라고 함
프로세스의 컨텍스트 스위칭
- 그림과 같이 프로세스 자체가 소유하고 있는 메모리 블록이 존재하고, 기존 프로세스 정보를 유지하기 위해선 해당 프로세스가 가지고 있던 실행 컨텍스트 외에 메모리 전환이 필요
스레드의 컨텍스트 스위칭
- 스레드는 기본적으로 운영체제의 공유 메모리 영역을 사용하지만, 스레드 역시 실행 컨텍스트들을 저장할 레지스터를 가지고 있고 이를 교환
멀티 스레드
- 일반적인 경우에서 프로그램의 구현은 대부분 싱글 스레드와 싱글 프로세스로 동작
- 이외에 다중 스레드를 이용하여 프로그램을 구성하는 경우를 멀티 스레드라고 칭함
- 멀티 스레딩을 사용함으로서 발생하는 문제 중 공유 메모리 영역에 대한 접근 문제가 있음
데드락과 해결법
JVM에서 메모리 모델
- JVM은 운영체제에게 일정 메모리 영역을 할당, 해당 메모리 영역을 자바 애플리케이션 코드가 사용
- JVM에서 자바 스레드(사용자 레벨 스레드)들은 각 스레드 스택에 지역 변수와 메소드를 할당하고, 힙 메모리 영역의 객체를 공유함
- 이렇게 메모리 영역을 공유하면서 발생하는 필연적 문제로 데이터 무결성과 정합성이 있는데, 이를 방지하기 위해 동기화(Syncronized), LOCK 등을 통해 각 스레드의 상태를 안전하게 접근할 수 있는 Thread-Safe를 구현함
데드락
- Thread-Safe를 위해 사용한 LOCK으로 인해 발생하는 문제로 Dead-Lock(교착 상태)이 있음
- 가장 쉽게 데드락을 볼 수 있는 곳은 데이터 베이스 접근으로 데이터 베이스는 메모리 공유 문제를 해결하기 위해 LOCK을 사용하고 있기때문임
- 데드락은 메모리 영역을 안전하게 공유하기 위해 사용한 락에 의해 오히려 아무것도 하지 못하는 상태를 의미, 데드락이 실제로 일어나기 위해선 4가지 필요 조건이 존재함
- 상호 배제(Mutual exclusion): 해당 자원에 대한 Critical Section(임계 구역)을 지정하여 동시에 자원에 접근할 수 없음
- 점유 대기(Hole and wait): 이미 자원을 선점한 상태에서 다른 프로세스의 자원을 기다리는 상태
- 비선점(No preemption): 프로세스 자체가 어떤 자원의 사용을 끝낼 때까지 해당 자원을 CPU가 재할당 할 수 없는 상태
- 순환 대기(Circular wait): 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 가짐
데드락의 해결
- 데드락은 각각 별개의 조건이 아닌 모든 조건이 이루어져야 발생하고, 순환 대기의 경우 2번과 3번이 없다면 발생하지 않음
- 따라서 데드락의 해결에는 여러 방법이 있지만 대부분 실현이 불가능한 방법이고, 이 중 순환 대기를 예방하는 방법이 주로 사용됨
- 자원의 낭비가 발생하더라도 각 자원에 대한 순위를 매겨 해당 순위 대로만 자원에 접근할 수 있도록 순차 대기 형태로 변경
싱글 스레드의 구현이 더 유리한 경우는?
- 싱글 스레드의 구현이 유리한 경우는 단일 자원을 활용 해야할 경우, 싱글 코어인 경우 컨텍스트 스위칭 비용의 최소화
데몬 스레드의 개념과 대표적인 사용 예
- 데몬 스레드는 주 스레드에서 파생된 보조 스레드로 백그라운드 서비스 작업을 수행
- 주 스레드 종료 시 데몬 스레드는 대부분 같이 종료되며, 자바의 경우 실행 중인 스레드가 데몬 스레드뿐일 경우 JVM 자체가 종료됨
- 데몬 스레드의 가장 가깝고도 대표적인 사용 예는 문서의 자동 저장과 자바 GC가 있음
- 일정 시간마다 저장의 역할을 하는 데몬 스레드
- 일정 시간마다 GC의 Mark&Sweep