hyeonga_code

JVM_19_스레드 종류 본문

JVM

JVM_19_스레드 종류

hyeonga 2024. 5. 11. 06:59
반응형

 

 

스레드 종류

 


- 프로그램이 동작하는 단계

[               User   Program           ]
---------------------------------------------
[                 OS    Kernel              ]
---------------------------------------------
[  Memory  ] [  CPU  ] [  Devices ]   => ( Hardware )

 

 

코어의 고민

메모리에서 데이터를 기다리는 시간이 꽤 오래 걸립니다.
코어에서 프로그램이 실행될 때 프로그램의 각종 연산 작업 등의 메모리에 접근하는 과정이 오래 걸려 CPU를 낭비하게 됩니다.
메모리를 기다리는 과정에 다른 CPU를 실행하게 하는 방법을 고민하게 됩니다.


코어에서 작성한 프로그램을 실행할 때 연산 작업(compute)을 하게 됩니다.
이 과정에서 메모리에 접근하면서 데이터를 처리합니다.
메모리에 접근할 때마다 코어가 멈춰있으므로 쉬게 되는 것입니다.
메모리 접근 과정에서 다른 작업을 실행하도록 합니다.

CORE [ compute ] [ memory ] [ compute ] [ memory ]...
                              [ compute ] [ memory ] [ compute ] ..

 

코어는 하나지만 두 개의 서로 다른 스레드를 실행하는 데 각각의 스레드를 Hardware Thread라고 합니다.
인텔의 hyper-threading 물리적인 코어마다 하드웨어 스레드가 두 개로 구성됩니다.

 

 

Hardware Thread

OS 관점에서 가상의 코어를 의미합니다.


싱글 코어 CPU에 하드웨어 스레드가 두 개인 경우 OS는 이 CPU를 듀얼 코어로 인식합니다. 듀얼 코어에 맞춰 OS 레벨의 스레드들을 스케줄링합니다.

 

 

Q. 인텔 듀얼 코어 CPU에 hyper-threading 이 적용된 경우 하드웨어 스레드는 총 몇 개인가?
A. CPU 하나에 두 개의 코어가 있고, 하나의 코어에 두 개의 hardware thread가 있으므로 총 4개의 하드웨어 스레드가 있습니다.

 

Native Thread

OS Thread = Native Thread = Kernel Thread

OS Kernel과 관련되어 있습니다.
일반적으로 알고 있는 스레드를 의미합니다.
OS Kernel 레벨에서 생성되고 관리되는 스레드입니다.
CPU에서 실제로 실행되는 단위입니다. 즉 CPU 스케줄링의 단위입니다.


Kernel
운영체제의 핵심으로 시스템의 전반을 관리, 감독하는 역할입니다.
하드웨어와 관련된 작업을 직접 수행합니다.
OS 스레드의 컨텍스트 스위칭은 커널이 주도적으로 진행합니다.
유저 모드에서 커널 모드로 전환되어 스레드를 처리하고, 종료되면 다시 유저 모드로 전환되며 시간적, 비용이 증가합니다.
사용자 코드와 커널 코드 모두 OS 스레드에서 실행됩니다.

작성한 코드가 OS 스레드에서 실행되다가 System Call을 사용하게 되면 커널 모드로 전환됩니다.
커널 모드에서 커널 코드를 실행하는데 OS 스레드에서 커널 코드가 실행됩니다.
종료되면 다시 OS 스레드에서 실행되게 됩니다.

 

 

Q. OS 스레드 여덟 개가 하이퍼 스레딩이 적용된 인텔 듀얼 코어 위에서 동작할 때, OS 스레드들을 어떻게 코어에 균등하게 할당할 수 있을까?

A. 두 개의 코어에 각각 하드웨어 스레드가 두 개씩 있어 총 네 개의 코어로 인식됩니다.
즉 각각의 하드웨어 스레드에 두 개의 OS 스레드가 할당되며 하나의 코어에 네 개의 OS 스레드가 할당됩니다.

 


다른 맥락에서의 Kernel Thread
OS Kernel의 역할을 수행하는 스레드를 의미합니다.

 

User Thread

User Program과 관련된 스레드입니다.
스레드의 개념을 프로그래밍 레벨에서 추상화한 것입니다.

Thread thread = new Thread();
thread.start();

 

`Thread` : 유저 레벨의 스레드를 의미합니다.
Java 에서 제공하는 Thread 클래스에는 start() 메소드가 있습니다.
start() 메소드를 호출하는데 JNI 기술을 통해 아래 레벨인 OS Kernel 의 System Call 을 호출합니다.
운영 체제가 리눅스인 경우 clone()을 호출하고, clone() 메소드는 OS 레벨의 스레드를 생성합니다.
Thread()가 생성된 스레드와 연결됩니다.

 

유저 스레드가 CPU에서 실행되려면 OS 스레드와 반드시 연결되어야 합니다.
CPU에서 실행되기 위해서는 User Program에 위치한 User Thread는 OS Kernel에 위치한 OS Thread와 연결되어야 합니다.


다른 맥락에서의 User Thread
OS 와는 독립적으로 유저 레벨에서 스케줄링되는 스레드를 의미합니다. Many-to-One, Many-to-Many Model 에서의 유저 스레드를 의미합니다.

 

 

 

스레드 생성과 관리

1. 유저 스레드

운영 체제의 커널이 관리하지 않는 스레드로 사용자 레벨 라이브러리나 프레임어크에 의해 관리됩니다.
유저 스레드는 커널 스레드보다 더 가볍고 빠르게 생성 및 관리될 수 있습니다.


2. 커널 스레드

운영체제의 커널에 의해 직접 관리되는 스레드입니다.
이들을 시스템 리소스에 직접적으로 접근하고 보다 안정적인 멀티태스킹을 가능하게 합니다.


스레드 생성

new Thread() : 스레드 객체를 생성하는 행위로 이 자케로는 스레드가 실행되지 않습니다.
start() 메소드 호출은 실제 스레드를 생성하고 실행하는 과정으로 이 때 운영 체제의 스케줄러가 스레드 관리를 시작합니다. 이 과정에서 커널 스레드와의 매핑이 이루어지며 스레드 실행을 운영 체제가 통제합니다.

 

 

Java 스레드 객체와 운영 체제의 스레드 객체의 연관 관계

유저 스레드와 OS 스레드를 어떻게 연결시킬 것인가?

1. One-to-One Model

유저 스레드와 OS 레벨의 스레드가 일대일로 연결됩니다.
스레드의 관리를 OS 에 위임하여 스케줄링, 관리합니다.
스케줄링도 커널이 수행합니다.
CPU가 멀티 코어를 가지고 있는 경우에도 잘 활용할 수 있습니다.


P1 [ T1, T2, T3 ]
한 프로세스가 여러 개의 스레드를 가질 수 있습니다.
일대일 매핑 관계이므로 T2의 스레드가 블록이 되어도 다른 스레드는 동작합니다.
그러나 Race Condition 이 발생할 수 있습니다.

 

 

2. One-to-Many Model

여러 개의 유저 스레드가 하나의 OS 스레드에 연결됩니다.
유저 레벨에서만 컨텍스트 스위칭이 발생하고 커널에서는 발생하지 않으므로 컨텍스트 스위칭이 빠릅니다.
CPU에서 실행되는 것은 하나의 OS 스레드이므로 Race Condition이 일어난다면 유저 레벨에서만 발생할 수 있습니다.
하나의 OS 스레드만 존재하므로 멀티 코어를 활용할 수 없습니다.


P1 [ T1, T2, T3 ]
하나의 스레드가 블록이 되는 경우 모든 스레드가 블록됩니다.
> nonblock I/O 사용**

 

 

3. Many-to-Many Model

여러 개의 유저 스레드가 서로 스케줄링 되어 여러 OS 스레드와 연결됩니다.
하나의 유저 스레드가 블록되더라도 다른 유저 스레드는 실행됩니다.
구현이 복잡합니다.

 

 

Green Thread

Java 초창기 버전에서는 Many-to-One Model을 사용했습니다. 이 때의 유저 스레드를 의미합니다.
확장되어 Many-to-Many Model의 유저 스레드도 포함됩니다.
OS와는 독립적으로 유저 레벨에서 스케줄링 되는 스레드를 의미합니다.

맥락에 따라 User Thread와 Green Thread의 의미가 같다고 볼 수 있습니다.

 

 

반응형