Java 21(LTS)에 새롭게 추가된 경량 스레드로, OS 스레드를 그대로 사용하지 않고, JVM 내부 스케줄링을 통해서, 수10만~수100만개의 스레드를 동시에 사용할 수 있게 제공하는 기능
기존의 전통적인 Java Thread에 더하여, Java 21에 새롭게 추가된 경량 스레드
Project Loom의 결과물로 추가된 기능으로, OS 스레드를 그대로 사용하지 않고, JVM 자체적으로 내부 스케줄링을 통해서 사용할 수 있는 경량의 스레드를 제공한다.
하나의 Java 프로세스가 수10만~수100만개의 스레드를 동시에 실행할 수 있게끔 설계되었다.
기존의 KLT(kernel-level thread)와 ULT(user-level thread)를 1:1 매핑하여 사용하는 JVM의 스레드 모델을 개선한, 여러 개의 가상 스레드를 하나의 네이티브 스레드에 할당하여 사용하는 모델
Virtual Thread의 등장배경이란 무엇인가요?
전통적인 Java의 Thread
Java의 Thread는 OS Thread를 Wrapping 한 것(Platform Thread)
Java 애플리케이션에서 Thread를 사용하면, 실제로는 OS Thread를 사용한 것
OS Thread는 생성 갯수가 제한적이고, 생성, 유지하는 비용이 비싸다.
따라서, 무한히 늘릴 수가 없다.
이 때문에 애플리케이션에서는 플랫폼 스레드를 효율적으로 사용하기 위해 Thread Pool을 사용했다.
어떻게 효율적으로 사용하는건가?
Reactive Programming
Webflux : 스레드를 대기하지 않고, 다른 작업 처리 가능
코드를 작성하고 이해하는 비용이 높다.
Reactive 하게 동작하는 라이브러리 지원을 필요로 한다.
기본적으로 자바는 스레드 중심으로 디자인되어 있다.
Exception Stack trace, Debugger, Profiling 모두 스레드 기반이다.
따라서, Reactive 할 때 작업이 하나의 스레드가 아닌 여러 스레드를 거쳐 처리되다 보니, 컨택스트 확인이 어려워, 디버깅이 어렵다.
따라서, 높은 처리량을 확보했지만, 개발 생산성이 낮아지게 되는 단점이 있다.
Virtual Thread가 해결하고자 하는 문제
문제 1. 애플리케이션의 높은 처리량(throughput) 확보
Blocking 발생시, 내부 스케줄링을 통해 다른 작업을 처리할 수 있게 하면, Blocking IO 타입동안 놀게 되는 스레드를 줄이게 할 수 있다.
문제 2. 자바 플랫폼의 디자인과 조화를 이루는 코드 생성
기존 스레드 구조 그대로 사용할 수 있도록 디자인되었다. 코드를 보면, Thread를 그대로 extends 한다. 따라서, 기존에 Thread에서 사용하고 있는 메서드를 그대로 사용할 수 있다.
Virtual Thread의 장점
Reactive 처럼 높은 처리량을 가지면서, MVC 처럼 동기적인 코드를 작성함으로써 코드를 쉽게 작성할 수 있다.
Virtual Thread의 구조
기존 Thread 구조
Virtual Thread 구조
Carrier Thread : Platform Thread와 거의 동일한 형태
실제 애플리케이션에서는 Carrier Thread를 사용하지 않고, Virtual Thread를 사용한다.
Virtual Thread 동작원리
Virtual Thread가 어떠한 작업을 할당 받아서, Carrier Thread와 1:1 매핑관계를 맺고 있다가,
Virtual Thread에서 Blocking이 발생하면, 이 Virtual Thread는 Carrier Thread에서 Unmount 된다.
그로 인해, Carrier Thread가 놀고 있으면, 다른 Virtual Thread에 Mount 된다.
기존에는 I/O 관련 Blocking이 발생했을 때, Carrier Thread 또는 Platform Thread가 계속 기다리기만 했었다. 그래서 비효율적이었다.
반면, Virtual Thread를 사용하면, 기다리지 않고, blocking이 발생한 Virtual Thread를 Unmount 시켜, 다른 Virtual Thread가 mount되어 작업을 수행할 수 있도록 한다.
Carrier Thread 또는 Platform Thread는 하드웨어에 의해 결정되므로 그 수가 정해져 있는 것에 비해, Virtual Thread는 수10만~수100만개 생성해서 사용할 수 있게 된다.
그런데, 이렇게 갯수가 많아지면, 데이터를 잘 관리해야 하기 때문에, 사용하는 자원도 상당히 작게 유지를 해야 한다.
Virtual Thread의 단점
Virtual Thread 사용법
자바코드
Spring Boot(MVC) 적용법
Virtual Thread 사용시, 유의사항
유의사항 1. 리소스라고 생각하지 말고, Task 별로 Virtual Thread 할당
Platform Thread가 Virtual Thread로 갈 때, 이것을
전통적인 OS의 자원이라고 생각하기 보다, Task 별로 할당하는 단위로 생각해야 함.
Platform Thread 하나를 Virtual Thread로 컨버팅하겠다라고 생각하면, 안된다.
기존에 전통적으로 Platform Thread로 작성된 코드를 또는 Thread pool의 코드를 그냥 Virtual Thread로 바꾸기만 하면, 그다지 성능상의 이점을 누릴 수 없다.
따라서, 개별 Task를 Virtual Thread로 할당한다라는 개념으로 접근해야 한다.
유의사항 2. Thread Local 사용시 주의
Platform Thread Pool을 사용할 때 공유를 위해 ThreadLocal을 사용하던 관습이 있다.
Virtual Thread는 Platform Thread와 다르게, 수10만~수100만개 생성해서 사용할 수 있고 Heap을 사용하기 때문에, 그 내부에서 ThreadLocal를 남발하게 되면, 메모리를 엄청나게 점유하게 되면서 메모리 이슈가 발생한다.
따라서, Thread Local를 사용시에, Virtual Thread로 동작할 때는 다시 한번 생각해봐야 한다.
유의사항 3. synchronized 사용시 주의
synchronized 사용시, Virtual Thread에 연결된 Carrier Thread가 Blocking 될 수 있으니 주의해야 한다. (-> 이 경우를 pinning 이라고 한다. 이런 상황을 직접적으로 마주할일은 많지는 않다.)
Virtual Thread 성능 테스트
성능 테스트 1 : 비즈니스 처리 로직에 thread가 blocking 되는 상황 가정
I/O Blocking이 발생하는 경우, Virtual Thread가 더 좋은 처리량을 보여준다.
성능 테스트 2 : 쿼리를 직접 질의(예상 소요시간 1초로 가정)를 하는 상황
Tomcat servlet이 Virtual Thread로 (no pool, virtual thread per task) Throughput을 뒤로 넘길 때, DB Connection을 가져오다 Timeout 발생 -> 이런 경우를 Overwhelming이라고 부른다.
Virtual Thread 적합한 사용처
I/O Blocking이 발생하는 경우, Virtual Thread가 적합하다.
CPU Intensive 작업(예 : 이미지 프로세싱해서 썸네일 만들기, 동영상 인코딩 등)에는 적합하지 않다. -> 왜 적합하지 않지?
만약 CPU에 종속적인 작업들(json 변환, 연산 등)만 존재한다면 성능이 개선되지 않는다. 왜냐하면 프로세서 코어가 실질적으로 스레드를 가지고 일을 하는데, 코어가 놀지 않고 계속해서 일을 한다면 스레드가 많다고 하더라도 코어가 부족하여 처리량이 향상될 수 없기 때문이다. 성능 향상은 I/O 작업에 의해 스레드가 블로킹될 때, 놀고 있는 코어를 활용해야 가능하다.
출처: https://mangkyu.tistory.com/309 [MangKyu's Diary:티스토리]
하나의 작업 주체가 여러 작업을 빠르게 바꿔가며 마치 동시에 진행하는 것처럼 하는 것으로 멀티 쓰레딩이라고 보면 된다. 동시에 실행되기 때문에, 하나의 공유자원에 접근한다면,레이스컨디션과 같은 임계영역 문제가 발생하기 쉽다. 그렇기에 항상 사용하는 자원에 대해 lock을 걸고 접근해야 하는 규칙이 존재한다.
동시성은 CPU Bound 보다 IO Bound에 적용하면 더 좋다. 왜냐하면, CPU Bound에서는 컨텍스트 스위치 비용이 더 커질 수 있기 때문이다. 반면, 처리 속도가 느려 스위칭 회수가 적은 IO Bound에서는 아주 적합하다고 할 수 있다.
Virtual Thread 란 무엇인가?
Java 21(LTS)에 새롭게 추가된 경량 스레드로, OS 스레드를 그대로 사용하지 않고, JVM 내부 스케줄링을 통해서, 수10만~수100만개의 스레드를 동시에 사용할 수 있게 제공하는 기능
기존의 전통적인 Java Thread에 더하여, Java 21에 새롭게 추가된 경량 스레드
Project Loom의 결과물로 추가된 기능으로, OS 스레드를 그대로 사용하지 않고, JVM 자체적으로 내부 스케줄링을 통해서 사용할 수 있는 경량의 스레드를 제공한다.
하나의 Java 프로세스가 수10만~수100만개의 스레드를 동시에 실행할 수 있게끔 설계되었다.
기존의 KLT(kernel-level thread)와 ULT(user-level thread)를 1:1 매핑하여 사용하는 JVM의 스레드 모델을 개선한, 여러 개의 가상 스레드를 하나의 네이티브 스레드에 할당하여 사용하는 모델
Virtual Thread의 등장배경이란 무엇인가요?
전통적인 Java의 Thread
Reactive Programming
Webflux : 스레드를 대기하지 않고, 다른 작업 처리 가능
코드를 작성하고 이해하는 비용이 높다.
Reactive 하게 동작하는 라이브러리 지원을 필요로 한다.
기본적으로 자바는
스레드
중심으로 디자인되어 있다.Exception Stack trace, Debugger, Profiling 모두 스레드 기반이다.
따라서, Reactive 할 때 작업이 하나의 스레드가 아닌 여러 스레드를 거쳐 처리되다 보니, 컨택스트 확인이 어려워, 디버깅이 어렵다.
따라서, 높은 처리량을 확보했지만, 개발 생산성이 낮아지게 되는 단점이 있다.
Virtual Thread가 해결하고자 하는 문제
문제 1. 애플리케이션의 높은 처리량(throughput) 확보
문제 2. 자바 플랫폼의 디자인과 조화를 이루는 코드 생성
Virtual Thread의 장점
Virtual Thread의 구조
기존 Thread 구조
Virtual Thread 구조
Virtual Thread 동작원리
Virtual Thread가 어떠한 작업을 할당 받아서, Carrier Thread와 1:1 매핑관계를 맺고 있다가,
Virtual Thread에서 Blocking이 발생하면, 이 Virtual Thread는 Carrier Thread에서 Unmount 된다.
그로 인해, Carrier Thread가 놀고 있으면, 다른 Virtual Thread에 Mount 된다.
기존에는 I/O 관련 Blocking이 발생했을 때, Carrier Thread 또는 Platform Thread가 계속 기다리기만 했었다. 그래서 비효율적이었다.
반면, Virtual Thread를 사용하면, 기다리지 않고, blocking이 발생한 Virtual Thread를 Unmount 시켜, 다른 Virtual Thread가 mount되어 작업을 수행할 수 있도록 한다.
Carrier Thread 또는 Platform Thread는 하드웨어에 의해 결정되므로 그 수가 정해져 있는 것에 비해, Virtual Thread는 수10만~수100만개 생성해서 사용할 수 있게 된다.
그런데, 이렇게 갯수가 많아지면, 데이터를 잘 관리해야 하기 때문에, 사용하는 자원도 상당히 작게 유지를 해야 한다.
Virtual Thread의 단점
Virtual Thread 사용법
자바코드
Spring Boot(MVC) 적용법
Virtual Thread 사용시, 유의사항
유의사항 1. 리소스라고 생각하지 말고, Task 별로 Virtual Thread 할당
유의사항 2. Thread Local 사용시 주의
유의사항 3. synchronized 사용시 주의
pinning
이라고 한다. 이런 상황을 직접적으로 마주할일은 많지는 않다.)Virtual Thread 성능 테스트
성능 테스트 1 : 비즈니스 처리 로직에 thread가 blocking 되는 상황 가정
성능 테스트 2 : 쿼리를 직접 질의(예상 소요시간 1초로 가정)를 하는 상황
Overwhelming
이라고 부른다.Virtual Thread 적합한 사용처
I/O Blocking이 발생하는 경우, Virtual Thread가 적합하다.
CPU Intensive 작업(예 : 이미지 프로세싱해서 썸네일 만들기, 동영상 인코딩 등)에는 적합하지 않다. -> 왜 적합하지 않지?
Spring MVC 기반 Web API 제공시, 편리하게 사용할 수 있다.
Virtual Thread vs Kotlin coroutine
Reference
https://findstar.pe.kr/2023/04/17/java-virtual-threads-1/
https://mangkyu.tistory.com/309
https://www.youtube.com/watch?v=vQP6Rs-ywlQ&ab_channel=kakaotech
위 영상 발표자의 블로그 1 : https://findstar.pe.kr/2023/04/17/java-virtual-threads-1/
위 영상 발표자의 블로그 2 : https://findstar.pe.kr/2023/07/02/java-virtual-threads-2/
https://www.youtube.com/watch?v=_lp3ohne-i8&ab_channel=%EC%B5%9C%EB%B2%94%EA%B7%A0
https://www.youtube.com/watch?v=srpOD6WIasM&ab_channel=%EC%B5%9C%EB%B2%94%EA%B7%A0
https://www.techwell.com/techwell-insights/2023/11/java-introduces-virtual-threads