[Java] 멀티스레딩 - 가상 스레드

2024. 11. 4. 14:10·백엔드/Java

 

가상 스레드를 이해하기 위해선 일단 JVM 스레드와 OS 스레드를 구분할 수 있어야 한다.

 

JVM 스레드 (플랫폼 스레드), OS 스레드


 

 

두 스레드의 흐름은 다음과 같다.

  1. JVM에 있는 스레드가 start() 되면 새로운 OS 스레드를 만들어달라고 OS에 요청한다.
  2. 새로운 OS 스레드가 생성될 때, JVM은 OS에게 요청하여 이 스레드에 필요한 스택 공간을 할당받는다.
  3. 이 OS 스레드가 CPU에 접근하여 JVM Thread가 하고자하는 작업을 수행한다.

 

결국 OS는 스택 할당 및 CPU 스케줄링의 과정을 도맡아 하기 때문에, JVM 스레드의 실행에 대해 책임이 있다. JVM 스레드는 OS 스레드로 매핑된 후 CPU에서 실행되며, 이 과정에서 OS의 스케줄링 알고리즘에 따라 실행 순서가 결정되기 때문이다.

 

 

이게 지금까지 공부하고 사용했던 스레드이다.

 

 

그리고 여기서 사용했던 JVM 스레드를 지금부터 플랫폼 스레드 혹은 캐리어 스레드라고 부르겠다.

 

 

보통 가상 스레드가 할당되지 않는 상태엔 플랫폼 스레드라고 하고, 가상 스레드가 할당된 상태엔 캐리어 스레드라고 부르는 편이다.

 

 

 

가상 스레드


 

가상 스레드는 위의 이미지를 보다시피 OS에 의해 관리되지 않고 JVM에 완전히 속해서 JVM의 관리를 받고, 각각의 스레드마다 스택도 할당되지 않는다.

 

 

그러면 사용자의 요청을 처리하기 위해 CPU에 어떻게 접근할까?

 

→ 여기서 위에서 언급했던 플랫폼 스레드와 OS 스레드가 사용된다.

 

 

기존의 플렛폼 스레드가 OS 스레드를 통해 스케줄링되고, 작업을 처리하는 방식은 동일하다. 그 대신 기존의 플랫폼 스레드에 직접적으로 작업이 담기지 않고, 먼저 가상 스레드에 담긴 후, 이 가상 스레드가 플랫폼 스레드에 마운트된다.

 

 

이는 가상 스레드가 더 효율적으로 관리되고, 많은 수의 가상 스레드를 손쉽게 생성하고 실행할 수 있게 한다.

 

 

만약 스레드의 작업이 모두 종료되면 가상 스레드와 플랫폼 스레드가 언마운트되고, 그 가상 스레드는 GC의 대상이 되어 제거된다.

 

 

만약 특정 스레드의 작업이 종료되지 않았고, 해당 작업을 더 이상 진행할 수 없는 상태라면 플랫폼 스레드와 가상 스레드는 언마운트된 후, 스레드의 상태를 힙 영역에 저장한다.

 

 

이 때 힙에는 스레드의 명령어 포인터와 스택이 스냅샷 형태로 저장된다.

 

→ 이러한 기능 덕분에 만약 플랫폼 스레드1 에서 작업을 하다가 언마운트된 경우, 굳이 플랫폼 스레드1 에서 작업을 재개하는 것이 아니라, 플랫폼 스레드2 에서 작업을 이어 할 수 있는 것이다.

 

 

가상 스레드 예제 코드1

public class VirtualThreads {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> System.out.println("실행되고 있는 스레드 : " + Thread.currentThread());
        Thread virtualThread = Thread.ofVirtual().unstarted(runnable);
        virtualThread.start();
        virtualThread.join();
    }
}

 

위의 코드를 실행하면 아래의 결과가 나온다.

실행되고 있는 스레드 : VirtualThread[#21]/runnable@ForkJoinPool-1-worker-1

 

이 로그의 의미는

  • VirtualThread[#21] : 이 스레드는 가상 스레드이며, ID는 21이다.
  • ForkJoinPool-1-worker-1 : 가상 스레드를 실행할 플랫폼 스레드 풀(ForkJoinPool)을 나타내고, 풀 내부의 플랫폼 스레드 중 1번 스레드를 할당한 것이다.

 

 

(참고) 플랫폼 스레드 풀

 

플랫폼 스레드 풀이란, 말 그대로 플랫폼 스레드를 보관하는 저장소이다. 그리고 이 스레드 풀의 수는 CPU의 코어 수와 동일하다.

 

그리고 위에서 설명했던, 가상 스레드 작업이 중단된 경우, 굳이 이전에 진행했던 플랫폼 스레드에서 작업을 진행하지 않을 수 있다고 했는데, 이 과정을 코드로 구현해봤다.

 

 

 

가상 스레드 예제 코드2

public class VirtualThreads {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            System.out.println("시작할 때 할당받은 스레드 : " + Thread.currentThread());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("끝날 때 할당받은 스레드 : " + Thread.currentThread());
        };
        Thread virtualThread1 = Thread.ofVirtual().unstarted(runnable);
        Thread virtualThread2 = Thread.ofVirtual().unstarted(runnable);

        virtualThread1.start();
        virtualThread2.start();

        virtualThread1.join();
        virtualThread2.join();
    }
}
시작할 때 할당받은 스레드 : VirtualThread[#22]/runnable@ForkJoinPool-1-worker-2
시작할 때 할당받은 스레드 : VirtualThread[#21]/runnable@ForkJoinPool-1-worker-1
끝날 때 할당받은 스레드 : VirtualThread[#22]/runnable@ForkJoinPool-1-worker-3
끝날 때 할당받은 스레드 : VirtualThread[#21]/runnable@ForkJoinPool-1-worker-2

 

이 로그를 보다시피 VirtualThread[#21] 와 VirtualThread[#22] 모두 작업 시작할 때 할당받은 플랫폼 스레드와 잠깐 중단된 후, 종료할 때 할당받은 플랫폼 스레드가 다르다.

 

  • VirtualThread[#21]
    • 시작 : worker-1
    • 종료 : worker-2
  • VirtualThread[#22]
    • 시작 : worker-2
    • 종료 : worker-3

 

 

'백엔드 > Java' 카테고리의 다른 글

[Java] SOLID (1) (Feat : 클린 아키텍처)  (0) 2025.02.05
[Java] 리플렉션  (0) 2024.11.07
[Java] 멀티스레딩 - 스레드 간 통신  (2) 2024.11.04
[Java] 멀티스레딩 - 락 심화  (0) 2024.11.04
[Java] 멀티스레딩 - 스레드간 데이터 공유  (0) 2024.10.31
'백엔드/Java' 카테고리의 다른 글
  • [Java] SOLID (1) (Feat : 클린 아키텍처)
  • [Java] 리플렉션
  • [Java] 멀티스레딩 - 스레드 간 통신
  • [Java] 멀티스레딩 - 락 심화
오도형석
오도형석
  • 오도형석
    형석이의 성장일기
    오도형석
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • MSA 모니터링 서비스
        • DB
      • 스파르타 코딩클럽
        • SQL
        • Spring
      • 백엔드
        • Internet
        • Java
        • DB
      • 캡스톤
        • Django
        • 자연어처리
      • Spring
        • JPA
        • MSA
      • ETC
        • ERROR
      • 개발 일기 N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 인기 글

  • 태그

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
오도형석
[Java] 멀티스레딩 - 가상 스레드
상단으로

티스토리툴바