[자바] 가상 스레드

자바 19에서 프리뷰 기능으로 도입된 프로젝트 룸(Project Loom)의 가상 스레드(virtual thread)링크는 경량(lightweight) 스레드이다. 자바 20을 거쳐 자바 21에서 최종 릴리스링크되었다. 가상 스레드는 처리량이 많은 동시성 애플리케이션의 개발, 관리 및 관찰(observe)을 훨씬 용이하게 만든다. 요청 당 스레드를 할당하여 처리하는 서버 애플리케이션의 하드웨어 리소스 활용을 최적화하는 것이 가상 스레드 도입의 주 목적이다.

가상 스레드는 java.lang.Thread API를 사용하는 기존 코드가 최소한의 변경으로 가상 스레드를 사용할 수 있도록 지원한다. 또한 기존 JDK 도구를 사용하여 가상 스레드의 트러블슈팅, 디버깅 및 프로파일링을 쉽게 수행할 수 있다.


가상 스레드의 도입으로 변경되거나 대체되지 않는 것은 다음과 같다.

  • 기존 스레드 구현을 제거하거나 기존 애플리케이션을 가상 스레드를 사용하도록 조용히 마이그레이션하지 않는다.
  • 자바의 기본적인 동시성 모델을 변경하지 않는다.
  • 자바 언어나 라이브러리에 새로운 데이터 병렬 처리 구조를 제공하지 않는다. 스트림 API는 여전히 대규모 데이터 세트를 병렬로 처리하는데 선호되는 방법이다.


가상 스레드의 도입 배경

일반적으로 서버 애플리케이션은 클라이언트로부터 받은 요청 당 스레드를 할당하여 작업을 처리한다. 이러한 요청 당 스레드(thread-per-request) 방식에서는 서버의 처리 능력(낮은 응답시간 및 지연시간, 높은 처리량)이 스레드에 비례한다. 서버가 기존 보다 더 많은 요청을 처리하도록 만들기 위해서는 서버의 가용 스레드를 늘려야 한다.

기존 JDK의 스레드는 java.lang.Thread 인스턴스를 말한다. 이 스레드를 플랫폼 스레드(platform thread)라고 한다. 플랫폼 스레드는 OS(운영 체제) 스레드 상에서 자바 코드를 실행하며 플랫폼 스레드의 전체 라이프사이클 동안 OS 스레드를 캡처한다. 따라서 애플리케이션이 사용할 수 있는 플랫폼 스레드의 수는 OS 스레드의 수로 제한된다. 플랫폼 스레드는 일반적으로 운영 체제에서 유지 관리하는 큰 규모의 스레드 콜 스택(call stack) 및 기타 리소스 상에서 코드를 실행한다. 플랫폼 스레드는 모든 유형의 작업을 실행하는데 적합하지만 리소스가 제한적이다. 플랫폼 스레드는 스레드-로컬 변수인 ThreadLocal를 지원한다.

플랫폼 스레드는 요청 당 스레드 모델에서 한계가 명확하다. 플랫폼 스레드 수의 최대 개수 제한은 운영체제의 OS 스레드, 메모리에 의해 영향을 받는다. 하지만 메모리, 네트워크 연결과 같은 다른 리소스가 고갈되기 전에 제한된 OS 스레드 수가 애플리케이션의 성능을 제한한다. 즉, 플랫폼 스레드는 애플리케이션의 처리량을 하드웨어가 지원할 수 있는 것보다 훨씬 낮은 수준으로 제한한다. 스레드 풀링은 새 스레드를 시작하는데 드는 높은 비용을 피하는데 도움을 주지만 최대 스레드 수는 제한되어 있기 때문에 스레드 풀링이 OS 스레드에 의한 성능 제한을 해결할 수는 없다.

가상 스레드도 플랫폼 스레드와 마찬가지로 java.lang.Thread의 인스턴스이며 OS 스레드 상에서 코드를 실행한다. 그러나 가상 스레드는 플랫폼 스레드와 다르게 OS 스레드에 의해 제한되지 않는다. 가상 스레드에서 실행 중인 코드가 블로킹 IO 작업을 호출하면 자바 런타임은 해당 작업이 완료되어 이후 작업이 재개될 때까지 가상 스레드를 일시 중단(suspend)한다. 일시 중단된 가상 스레드와 연결된 OS 스레드는 다른 가상 스레드에 대한 작업을 수행할 수 있다.

플랫폼 스레드와 달리 가상 스레드는 콜 스택이 얕기 때문에 단일 HTTP 클라이언트 호출 또는 단일 JDBC 쿼리 정도만 수행하는 것이 일반적이다. 따라서 IO 작업이 완료될 때까지 기다리는 작업과 같이 대부분의 시간을 블로킹된 상태로 소비하는 작업을 실행하는데 적합한 반면 장시간 실행되는 CPU 집약적인 작업에는 적합하지 않다. 가상 스레드 또한 스레드 로컬 변수를 지원하지만 단일 JVM이 수백만 개의 가상 스레드를 지원할 수 있으므로 신중하게 사용해야 한다.

플랫폼 스레드와 가상 스레드의 공통점과 차이점을 정리하면 다음과 같다.

  • 공통점
    • OS 스레드 상에서 코드를 실행한다.
    • java.lang.Thread의 인스턴스이다.
  • 차이점
    • 플랫폼 스레드는 OS 스레드에 의해 제한되는 반면 가상 스레드는 제한되지 않는다.
    • 플랫폼 스레드는 제한된 리소스이며 생성 비용이 많이 들고 메모리 사용량이 많아 무겁다. 따라서 적절한 스레드 풀링(pooling) 과정을 통한 리소스 관리가 필요하다. 반면 가상 스레드는 플랫폼 그레드에 비해 넉넉한 리소스이며 생성 비용이 적게 들고 메모리 사용량이 적어 가볍다. 가상 스레드의 경우 풀링이 필요하지 않다.
    • 플랫폼 스레드는 콜 스택이 깊은 반면 가상 스레드는 콜 스택이 얕다.

##

피닝(pinning)

참고

Comments