Java Thread와 OS Thread

Lee Mingi
8 min readApr 14, 2024

--

1. Java Thread

자바에서는 프로그램이 실행되는 동안 따라갈 수 있도록 하는 경로라고 생각할 수 있습니다.

모든 프로그램은 JVM에서 제공되는 하나의 메인 스레드를 갖고 있고, 이들은 main() 메소드가 메인 스레드에 의해 호출됩니다.
JVM은 여러 스레드를 한 번에 실행할 수 있고, 이 때 우선순위에 따라 먼저 실행되는 스레드가 결정됩니다.

아래의 2가지 방법으로 Thread를 이용할 수 있습니다.

  • java.lang class
  • Runnable Interface

2. OS Thread

스레드란 고유한 실행 경로입니다.
작은 프로세스이기에 OS가 다른 스레드와 함께 작동되도록 스케줄링 진행하게 되는데, 이 때 생성된 프로그램들과 자원 공유를 진행 합니다.

즉, 하나의 애플리케이션 내에서 수많은 스레드가 협력할 수 있습니다.

Thread는 프로세스와 일부 특성을 공유하기에, 경량 프로세스라고도 불립니다. 각각의 스레드는 하나의 프로세스의 일부이며, 프로세스가 만약 멀티 스레드를 지원한다면, 많은 스레드를 컨트롤 할 수 있습니다.

아래의 크게 2가지 종류의 스레드가 있는데요.

  • 커널 수준 스레드
    사용자 수준 스레드보다 느리지만, OS는 시스템 호출을 사용해 이를 호출하며, OS가 인식하는 스레드입니다.
  • 사용자 수준 스레드
    OS는 사용자 수준 스레드를 인식하지 못하지만, Context Switch 속도가 커널 수준 스레드에 비해 빠르다.

3. Java Thread는 어떤 스레드인가?

Java Thread는 유저 수준 스레드지만, 내부적으로 JVM은 커널 스레드를 사용합니다. 커널 스레드 풀에 있는 커널 스레드에서 이용할 수 있도록 위임하여, 커널 스레드와 1:1 매핑을 통해 동작하게 됩니다.

초기에는 JVM이 스케줄링을 진행하는 Green Thread라는 방식을 이용하였나, 이후에 변경되어 현재는 OS의 정책에 따라 진행합니다.

Green Thread와 Native Thread에 대해 알아보겠습니다.
Green Thread란, OS 대신 런타임 라이브러리, 혹은 VM이 스레드를 스케쥴링 하는 기법입니다. 사용자 수준 스레드라고 생각할 수 있습니다.

Green Thread가 blocking system call을 진행하면 프로세스의 모든 스레드가 block되는데, 커널 수준 스레드는 이 시점에서 하나만 만들어지기에, 멀티 코어에선 장점을 활용하기 어렵습니다.

OS가 Thread API를 지원하지 않을 때 사용 가능하지만, 여러 CPU 코어를 이용 할 수는 없다는 단점이 있습니다.

Native Thread란 다음과 같습니다.

위에서 말한 OS에서 만들어진 스레드, 즉 커널 스레드라고 생각할 수 있습니다. Non-Green Thread라고 부르기도 하고, new Thread()로 부르게 되는 것이 OS Thread입니다.

4. 어떻게 OS Thread를 사용했는가

  • OS는 C/C++로 대부분 이루어져있기에, 거기에 맞도록 설정을 해야하고, 그를 위해 이용되는 것이 JNI(Java Native Interface)입니다.
public class Thread {
static AtomicInteger threadCount = new AtomicInteger(1);

public void run() {
System.out.println("Running Thread " + threadCount.getAndIncrement());
}

public void start() {
start0();
}
private native void start0();
}
  • start() 메소드의 native 키워드가 중요한데요, 이들은 C, C++ 등으로 작성된 메소드입니다. Native 메소드를 호출 할 때 JNI(Java Native Interface)로 구현되어 작동합니다.
pthread_t tid;
if (pthread_create(&tid, &attr, thread_entry_point, arg_to_entrypoint))
{
fprintf(stderr, "Error creating thread\\n");
return;
}
  • Linux 스레드에서 액세스를 위해서는 JVM JNI 객체와 자바 스레드 객체에 대한 권한이 있어야하고, → JavaThreadWrapper로 불러오게 됩니다.
JNIEXPORT void JNICALL Java_com_threading_Thread_start0(JNIEnv *env, jobject javaThreadObjectRef)
{
JavaThreadWrapper* args = new JavaThreadWrapper(env, javaThreadObjectRef);
}
  • JavaThreadWrapper에서 JVM에 대한 접근 권한과, 자바 스레드에 대한 참조가 가능해집니다.
void *thread_entry_point(void *args)
{
std::cout << "Starting thread_entry_point";

JavaThreadWrapper *javaThreadWrapper = (JavaThreadWrapper*)args;
javaThreadWrapper>callRunMethod();
delete javaThreadWrapper;
return NULL;
}
void JavaThreadWrapper::callRunMethod() {
JNIEnv *env = attachToJvm();
jclass cls = env->GetObjectClass(threadObjectRef);
jmethodID runId = env->GetMethodID(cls, "run", "()V");
if (runId != nullptr) {
env->CallVoidMethod(threadObjectRef, runId);

} else {
cout << "No run method found in the Thread object!!" << endl;
}
env->DeleteGlobalRef(threadObjectRef); //delete global ref before detaching the thread.
}
  • Linux에서 모든 스레드 객체에 대해 스레드를 만들고, JVM도 이와 비슷하게 작동하게 됩니다.

5. Light Weight Process

Linux의 Thread는 실제로는 Process입니다. 사용자 수준에서는 Thread와 Process가 구별되지만, 커널은 모두 Process로 관리하게 됩니다.

사용자 수준에서의 Thread 는커널 수준에서의 Light Weight Process(LWP) 라고 생각할 수 있습니다.

본래 Linux 커널에서는 Thread라는 개념이 없었기에, 다른 프로세스로 간주되었고, 멀티 스레드도 커널에선 단일 프로세스로 간주되었습니다.
즉, Thread가 아닌 커널 내부의 프로세스로 간주하기에 이를 경량 프로세스로 부르게되었습니다.

주소 공간같은 일부 리소스를 공유하지만, 다른 일반 프로세스보다 경량이기에 LWP라는 이름이 붙게 되었습니다.

따라서, Thread(사용자 수준) = LWP(커널 수준) 이 되는 것입니다.

정리

  • 자바에서의 Thread = 유저 수준 Thread
  • 이전에는 Green Thread라는 방법을 통하여 JVM에서 Thread를 관리했지만, 현재는 OS에서 관리한다.
  • 자바에서 쓰레드 생성 → native method 실행 후 커널과 1:1 매핑을 진행한다.
  • 경량 프로세스(LWP)라고 부르는 것은 Thread와 같은 용어이다.

Reference.

https://www.tutorialspoint.com/difference-between-os-thread-and-java-threads
https://www.geeksforgeeks.org/difference-between-java-threads-and-os-threads/
https://stackoverflow.com/questions/18278425/are-java-threads-created-in-user-space-or-kernel-space
https://stackoverflow.com/questions/2653458/understanding-javas-native-threads-and-the-jvm
https://en.wikipedia.org/wiki/Green_thread
https://medium.com/@unmeshvjoshi/how-java-thread-maps-to-os-thread-e280a9fb2e06
https://github.com/unmeshjoshi/jvmthreads
https://www.geeksforgeeks.org/native-keyword-java/
https://stackoverflow.com/questions/10484355/what-is-the-difference-between-lightweight-process-and-thread
https://www.thegeekstuff.com/2013/11/linux-process-and-threads/

--

--