Skip to content

2주차 월요일 그룹 3

이지표 edited this page Jul 1, 2024 · 5 revisions

프로세스

  • 실행 중인 프로그램의 인스턴스
  • 운영 체제로부터 자원을 할당받는 작업의 단위

하드웨어 스레드와 소프트웨어 스레드

  • 하드웨어
    • CPU에 의해 직접 실행되는 물리적 실행 단위
    • 프로세서 코어 내에 구현된 독립적인 실행 컨텍스트
    • 동시에 여러 명령어를 처리할 수 있게 해주어 성능을 향상
  • 소프트웨어
    • 운영 체제에서 관리하는 논리적 실행 단위
    • 하나의 프로세스 내에서 독립적으로 실행되는 작업 흐름
    • 커널 레벨 스레드
      • 네이티브 스레드, OS 커널에 의해 생성되고 관리되는 스레드
    • 유저 레벨 스레드
      • OS Thread개념을 프로그래밍 레벨에서 추상화 한 것
      • 프로그래밍 언어에서 제공한 라이브러리를 생성한 스레드를 의미
      • 프로그램 연산을 위해 물리적 스레드가 해주어야 함 → 운영체제가 관리하는 커널 스레드와 매핑되어 동작해야함
    • 유저 레벨 스레드와 커널 스레드의 매핑
      • Many To One
        • 블로킹 상태에 빠지면 유저 스레드가 모두 일을 하지 못함
      • One To One
        • 커널 스레드가 과도하게 생성될 수 있음
      • Many To Many
        • 다수의 커널 스레드로 유저 스레드를 제어하기 위하 별도의 스케줄러 필요

자바에서의 스레드

  • 전통적인 자바는 One To One 방식을 사용
  • 스케쥴러도 OS의 구현체데 의존함

JDK 1.1: Many To One

  • CPU Core가 하나인 환경에서 설계된 쓰레드
  • 멀티 코어 환경에서는 장점을 살리지 못해 사용되고 있지 않음

JDK 1.3 ~: One To One

  • 유저 스레드 생성시 커널 스레드와 1대1 방식으로 매핑
  • 자바에서는 OS스레드를 Wrapping하고, 이를 플랫폼 스레드라 함

Spring MVC

  • Spring MVC는 thread per request model
    • 요청 당 하나의 커널 스레드를 생성하여 멀티스레드로 처리하는 구조
  • OS 스레드는 생성, 관리 비용이 비싸 스레드 풀을 둠

Project Loom

  • Java에서 처리량이 높고 가벼운 동시성 모델을 지원하기 위한 프로젝트
  • OS대신 JVM에 의존하는 유저 레벨 스레드를 사용
  • 기존 플랫폼 스레드보다 효율적이고 가벼운 경량 스레드(Fiber)를 추가하는 목표

Fiber

  • Fiber는 JVM 인스턴스로 생성 및 관리됨
  • 메모리 사용량 측면에서 커널 스레드보다 훨씬 가볍기에 컨텍스트 스위칭 비용이 월등하게 적음

JDK 21: Virtual Thread

  • Fiber라는 별도의 기능으로 개발되었으나, 기존 스레드 문법과 호환될 수 있는 형태로 발전
  • Virtual Thread는 N:1로 Carrier Thread랑 매핑되고, Carrier Thread는 OS Thread와 매핑되는 구조
  • 플랫폼 스레드와 다르게 리소스가 매우 작기에, 리소스 회수를 임의로 하지 않고 GC에 위임

JVM의 스레드 동작

Thread 객체 초기화

Thread 객체가 생성될 때, JVM은 다음의 작업을 수행

  1. 메모리 할당 : Heap영역에 Thread 객체를 위한 메모리를 할당.
  2. 필드 초기화
  • threadStatus : 초기값 0(NEW 상태)
  • priority : 부모 스레드의 우선순위를 상속 (기본값 NORM_PRIORITY)
  • daemon : 부모 스레드의 데몬 상태를 상속
  1. 스레드 그룹 설정 : 부모 스레드의 스레드 그룹에 새 스레드를 추가

start() 메서드 실행

  1. 상태 검사 : threadStatus가 0인지 확인하여 이미 시작된 스레드가 아닌지 검사
  2. 스레드 등록 : JVM의 스레드 관리자에 새 스레드를 등록
  3. 네이티브 start0() 메서드 호출 : JNI(Java Native Interface)를 통해 네이티브 start0() 메서드를 호출.

JNI 및 네이티브 코드 실행

start0() 메서드는 JNI를 통해 다음 작업을 수행

  1. OS 스레드 생성 : 운영 체제의 스레드 생성 API 호출(예: Linux의 pthread_create)
  2. JVM 스레드 구조체 생성 : JavaThread 구조체를 생성하고 초기화
  3. 스레드 로컬 저장소(TLS) 설정 : 스레드별 데이터를 저장할 TLS를 초기화합니다.
  4. JNI 환경 설정 : 새 스레드를 위한 JNIEnv 구조체를 초기화

JavaThread 초기화

JavaTread 구조체는 다음 정보를 포함

  • OS 스레드 식별자
  • Java Thread 객체에 대한 참조
  • 스레드 상태 정보
  • 동기화 관련 데이터(예: parker, monitor 등)
  • 예외 처리 관련 정보

스레드 스택 설정

새 스레드를 위한 스택이 할당

  1. 스택 크기 결정: JVM 옵션 (-Xss)에 따라 결정되며, 기본값은 플랫폼에 따라 다르다.
  2. 가드 페이지 설정: 스택 오버플로우를 감지하기 위한 가드 페이지를 스택의 끝에 배치

운영 체제 레벨

OS 스레드 생성

  1. 스레드 컨택스트 생성 : 레지스터 세트, 프로그램 카운터 등을 포함한 스레드 컨텍스트 초기화
  2. 스택 할당 : 커널 모드 스택과 사용자 모드 스택을 할당
  3. 스레드 식별자 할당 : 고유한 스레드 ID를 할당

스케쥴링 설정

새 스레드를 위한 스케줄링 정보 설정

  1. 우선순위 설정 : Java 우선순위를 OS 우선순위로 매핑.
  2. 실행 큐 추가 : 스레드를 CPU의 실행 큐에 추가

스레드 실행 시작

  1. JVM으로의 제어 반환
    OS가 스레드 생성을 완료하면 제어권이 JVM으로 돌아옵니다.
  2. run() 메서드 호출 준비
    JVM은 새 스레드의 엔트리 포인트를 Thread.run() 메서드로 설정
  3. 스레드 상태 변경
    스레드 상태가 NEW에서 RUNNABLE로 변경
  4. 실행 시작
    OS 스케줄러에 의해 선택되면 새 스레드가 실제로 실행을 시작하고 run() 메서드의 코드를 실행

레퍼런스

https://docs.oracle.com/cd/E19620-01/805-4031/6j3qv1oed/index.html

👼 개인 활동을 기록합시다.

개인 활동 페이지

🧑‍🧑‍🧒‍🧒 그룹 활동을 기록합시다.

그룹 활동 페이지

🎤 미니 세미나

미니 세미나

🤔 기술 블로그 활동

기술 블로그 활동

📚 도서를 추천해주세요

추천 도서 목록

🎸 기타

기타 유용한 학습 링크

Clone this wiki locally