-
Notifications
You must be signed in to change notification settings - Fork 0
2주차 월요일 그룹 3
이지표 edited this page Jul 1, 2024
·
5 revisions
- 실행 중인 프로그램의 인스턴스
- 운영 체제로부터 자원을 할당받는 작업의 단위
- 하드웨어
- CPU에 의해 직접 실행되는 물리적 실행 단위
- 프로세서 코어 내에 구현된 독립적인 실행 컨텍스트
- 동시에 여러 명령어를 처리할 수 있게 해주어 성능을 향상
- 소프트웨어
- 운영 체제에서 관리하는 논리적 실행 단위
- 하나의 프로세스 내에서 독립적으로 실행되는 작업 흐름
- 커널 레벨 스레드
- 네이티브 스레드, OS 커널에 의해 생성되고 관리되는 스레드
- 유저 레벨 스레드
- OS Thread개념을 프로그래밍 레벨에서 추상화 한 것
- 프로그래밍 언어에서 제공한 라이브러리를 생성한 스레드를 의미
- 프로그램 연산을 위해 물리적 스레드가 해주어야 함 → 운영체제가 관리하는 커널 스레드와 매핑되어 동작해야함
- 유저 레벨 스레드와 커널 스레드의 매핑
- Many To One
- 블로킹 상태에 빠지면 유저 스레드가 모두 일을 하지 못함
- One To One
- 커널 스레드가 과도하게 생성될 수 있음
- Many To Many
- 다수의 커널 스레드로 유저 스레드를 제어하기 위하 별도의 스케줄러 필요
- Many To One
- 전통적인 자바는 One To One 방식을 사용
- 스케쥴러도 OS의 구현체데 의존함
- CPU Core가 하나인 환경에서 설계된 쓰레드
- 멀티 코어 환경에서는 장점을 살리지 못해 사용되고 있지 않음
- 유저 스레드 생성시 커널 스레드와 1대1 방식으로 매핑
- 자바에서는 OS스레드를 Wrapping하고, 이를 플랫폼 스레드라 함
- Spring MVC는 thread per request model
- 요청 당 하나의 커널 스레드를 생성하여 멀티스레드로 처리하는 구조
- OS 스레드는 생성, 관리 비용이 비싸 스레드 풀을 둠
- Java에서 처리량이 높고 가벼운 동시성 모델을 지원하기 위한 프로젝트
- OS대신 JVM에 의존하는 유저 레벨 스레드를 사용
- 기존 플랫폼 스레드보다 효율적이고 가벼운 경량 스레드(Fiber)를 추가하는 목표
- Fiber는 JVM 인스턴스로 생성 및 관리됨
- 메모리 사용량 측면에서 커널 스레드보다 훨씬 가볍기에 컨텍스트 스위칭 비용이 월등하게 적음
- Fiber라는 별도의 기능으로 개발되었으나, 기존 스레드 문법과 호환될 수 있는 형태로 발전
- Virtual Thread는 N:1로 Carrier Thread랑 매핑되고, Carrier Thread는 OS Thread와 매핑되는 구조
- 플랫폼 스레드와 다르게 리소스가 매우 작기에, 리소스 회수를 임의로 하지 않고 GC에 위임
Thread 객체가 생성될 때, JVM은 다음의 작업을 수행
- 메모리 할당 : Heap영역에 Thread 객체를 위한 메모리를 할당.
- 필드 초기화
- threadStatus : 초기값 0(NEW 상태)
- priority : 부모 스레드의 우선순위를 상속 (기본값 NORM_PRIORITY)
- daemon : 부모 스레드의 데몬 상태를 상속
- 스레드 그룹 설정 : 부모 스레드의 스레드 그룹에 새 스레드를 추가
- 상태 검사 : threadStatus가 0인지 확인하여 이미 시작된 스레드가 아닌지 검사
- 스레드 등록 : JVM의 스레드 관리자에 새 스레드를 등록
- 네이티브 start0() 메서드 호출 : JNI(Java Native Interface)를 통해 네이티브 start0() 메서드를 호출.
start0() 메서드는 JNI를 통해 다음 작업을 수행
- OS 스레드 생성 : 운영 체제의 스레드 생성 API 호출(예: Linux의 pthread_create)
- JVM 스레드 구조체 생성 : JavaThread 구조체를 생성하고 초기화
- 스레드 로컬 저장소(TLS) 설정 : 스레드별 데이터를 저장할 TLS를 초기화합니다.
- JNI 환경 설정 : 새 스레드를 위한 JNIEnv 구조체를 초기화
JavaTread 구조체는 다음 정보를 포함
- OS 스레드 식별자
- Java Thread 객체에 대한 참조
- 스레드 상태 정보
- 동기화 관련 데이터(예: parker, monitor 등)
- 예외 처리 관련 정보
새 스레드를 위한 스택이 할당
- 스택 크기 결정: JVM 옵션 (-Xss)에 따라 결정되며, 기본값은 플랫폼에 따라 다르다.
- 가드 페이지 설정: 스택 오버플로우를 감지하기 위한 가드 페이지를 스택의 끝에 배치
- 스레드 컨택스트 생성 : 레지스터 세트, 프로그램 카운터 등을 포함한 스레드 컨텍스트 초기화
- 스택 할당 : 커널 모드 스택과 사용자 모드 스택을 할당
- 스레드 식별자 할당 : 고유한 스레드 ID를 할당
새 스레드를 위한 스케줄링 정보 설정
- 우선순위 설정 : Java 우선순위를 OS 우선순위로 매핑.
- 실행 큐 추가 : 스레드를 CPU의 실행 큐에 추가
- JVM으로의 제어 반환
OS가 스레드 생성을 완료하면 제어권이 JVM으로 돌아옵니다. - run() 메서드 호출 준비
JVM은 새 스레드의 엔트리 포인트를 Thread.run() 메서드로 설정 - 스레드 상태 변경
스레드 상태가 NEW에서 RUNNABLE로 변경 - 실행 시작
OS 스케줄러에 의해 선택되면 새 스레드가 실제로 실행을 시작하고 run() 메서드의 코드를 실행
https://docs.oracle.com/cd/E19620-01/805-4031/6j3qv1oed/index.html