내가 만든 자바 코드가 어떤 과정으로 실행되는지 알아보기 위한 "JVM 알아보기" 마지막 포스팅입니다.

이번 포스팅에서는 Thread 와 Java Thread Model 에 대해 알아보겠습니다.

 

 


 

Thread

우리가 자바 프로그램을 실행하면 JVM 프로세스가 실행되고, JVM 프로세스 안에서 GC 를 포함한 여러 개의 스레드가 실행된다.

그리고 각 스레드마다 Java Stack, PC Register, Native Method Stack 이 존재한다.

이렇게 자바는 동일한 메모리를 읽지만 각각 작업을 수행하는 스레드들, 즉 멀티 스레드를 통해 동시에 여러 작업을 수행한다.

 

 

자바는 왜 프로세스를 여러 개 추가하지 않고 스레드라는 개념을 만든 것일까?

그 이유는 프로세스를 생성하려면 많은 시간과 자원이 필요하기 때문이다.

예를 들면, JVM 은 벤더마다 다르지만 최소 32MB 이상의 메모리가 필요하다.

그에 비해 스레드는 1MB 이내의 메모리를 점유한다. 그렇기 때문에 스레드를 경량 프로세스 라고도 부른다.

 

이번 포스팅에서는 스레드 모델의 변화와 그 이유를 중점으로 스레드에 대해 알아보도록 하겠다.

 

 

 

Multi Threading Model

 

스레드에는 사용자 수준 스레드(User Level Threads)커널 수준 스레드(Kernel Level Threads) 두 가지 유형이 있다.

 

먼저 두 가지 유형을 간단하게 알아보자.

사용자 수준 스레드는 사용자 라이브러리를 통해 사용자가 만든 스레드로, 스레드가 생성 된 프로세스의 주소 공간에서 해당 프로세스에 의해 실행되고 관리된다. 그리고 커널 수준 스레드는 커널에 의해 생성되고 운영체제에 의해 직접 관리된다. 사용자 수준 스레드보다 생성 및 관리 속도가 느리다.

 

두 유형의 차이는 누가 스레드를 제어하느냐에 있다.

사용자 수준 스레드는 스레드가 생성 된 프로세스 자체에 의해 제어되며, 커널은 프로세스 내의 사용자 스레드에 대해 알지 못한다.

커널 수준 스레드는 OS에 의해 직접 관리된다.

 

사용자 스레드를 실행한다고 가정해보자.

스레드를 실행하기 위해서는 커널의 CPU 스케줄러가 스레드를 CPU 에 스케줄링 해야 한다.

그런데 CPU 스케줄러는 커널의 일부이기 때문에 사용자 스레드에 대해 알지 못한다.

이러한 이유로 사용자 스레드는 커널 스레드에 매핑되어 실행하게 된다.

 

이 과정을 신제품 출시에 비유할 수 있다. 우리가 출시하려는 신제품은 사용자 스레드다.

이 제품을 판매하기 위해 제품의 회사를 정부에 등록해야한다. 여기서 회사는 프로세스, 정부는 커널이다.

회사는 상점에 입점을 하고, 입점을 위해서 정부의 규칙을 따라야한다. 이 상점이 커널 스레드다.

 

즉, 커널 스레드(상점)와 프로세스(회사)가 매핑되어 있고, 그 프로세스 내에서 사용자 스레드가 생성되기 때문에 커널에서 인식할 수 있는 것이다. 

 

 

커널 스레드와 사용자 스레드를 매핑하는 이유를 알아보았으니 이제 매핑 방법에 대해 알아보도록 하겠다.

매핑 방법에는 일반적으로 세 가지가 있다. 

 

 

Many-to-One Model, 다대일 모델

 

다대일 모델은 여러 사용자 스레드를 하나의 커널 스레드에 매핑한다. 스레드는 사용자 공간의 스레드 라이브러리에 의해 관리된다.

한 스레드가 Blocking 되는 경우에 전체 프로세스가 Block 된다.

한 번에 하나의 스레드만이 커널에 접근할 수 있기 때문에, 멀티 코어 시스템에서 병렬로 실행될 수 없다.

하지만 동기화 및 리소스 공유가 쉽기 때문에 실행 시간이 단축된다.

 

Java 의 초기 버전의 스레드 모델인 Green Thread 가 다대일 모델을 사용하였다.

대부분의 컴퓨터 시스템에서 멀티 코어가 표준이 되면서 그 이점을 살릴 수 없는 Green Thread 는 현재 Java 에서 사용되지 않는다.

 

 

 

One-to-One Model, 일대일 모델

 

일대일 모델은 각 사용자 스레드를 각각 하나의 커널 스레드에 매핑한다.

그렇기 때문에 하나의 스레드가 Blocking 되더라도 다른 스레드가 실행될 수 있기 때문에 병렬 실행이 용이하다.

 

이 모델의 단점은 사용자 스레드를 만들기 위해서는 커널 스레드를 만들어야 한다는 것이다.

많은 수의 커널 스레드는 시스템 성능에 부담을 줄 수 있기 때문에 Window 나 Linux 는 스레드 수의 증가를 제한한다.

 

 

Many-to-Many Model, 다대다 모델

 

다대다 모델은 여러 개의 사용자 스레드를 그보다 작은 수 혹은 같은 수의 커널 스레드로 멀티플렉스한다.

커널 스레드의 수는 응용 프로그램에 따라 다르다. 4코어 시스템보다 8코어 시스템에서 더 많은 커널 스레드를 할당받는다.

 

이전 두 모델의 단점을 절충한 방법으로, 개발자는 필요한 만큼 사용자 스레드를 생성하고 그에 상응하는 커널 스레드가 병렬로 수행될 수 있다. 가장 높은 정확도의 동시성 처리를 제공하는 모델로, 하나의 스레드가 Blocking 되었을 때 커널은 다른 스레드의 수행을 스케쥴할 수 있다.

 

또한, 다대다 모델은 two-level-model(두 수준 모델) 이라고도 불리는데

다대다 모델은 사용자 스레드가 하나의 커널 스레드에만 연결되는 일대일 모델로 동작하는 것도 허용하기 때문이다.

 

two level model

 

다대다 모델이 세 모델 중 가장 융통성있는 것 처럼 보이지만 실제로는 구현하기가 어렵다.

그리고 대부분의 시스템에서 코어 수가 증가하면서 커널 스레드를 제한하는 것의 중요성이 줄어들었다.

따라서 현재 대부분의 운영체제는 일대일 모델을 사용한다.

 

그렇다면 현재 자바의 스레드는 어떤 모델을 사용할까?

자바는 JDK 1.3 이후로 다대다 모델을 사용한다. 이를 Native Thread 라고 한다.

 

 

 

Green Thread vs. Native Thread

 

자바는 초기에는 Green Thread 를 사용하다가 Native Thread 로 스레드 모델을 변경하였다.

마지막으로 두 스레드 모델의 차이점을 정리하고 포스팅을 마치도록 하겠다.

 

 

 

 

마치며

 

그린 스레드는 커널의 개입 없이 사용자 레벨에서 관리하는 스레드 모델을 의미하고

네이티브 스레드는 현재 우리가 사용하는 스레드를 의미한다.

애플리케이션 수준에서 JVM 이 완전하게 관리하는 그린 스레드 모델은 멀티 코어 시스템이 보편화되면서 자바에서 사라졌다.

 

 

Reference

 

 

복사했습니다!