Multithreading

A thread is a sequence of control within a process. A single-threaded process follows a single sequence of control while executing. An MT process has several sequences of control, thus is capable of several independent actions at the same time. When multiple processors are available, those concurrent but independent actions can take place in parallel.

Multithreading Models

Green Threads - Many to One Model

Many user threads to One kernel thread(Many to One Model) 에서 모든 Thread 의 활동은 UserSpace 로 제한된다.

그림을 보면 알 수 있듯이, Additionally, only one thread at a time can access the kernel, so only one schedulable entity is known to the operating system. 즉, 여러개의 JavaThread 가 있더라도 딱 하나의 JavaThread 만 KernelThread 에 Mapping 된다고 보면된다. This changed in Java 1.2, and there has not been any support for it at the JVM level since.

One to One Model

One user thread to One kernel thread(One to One Model) 에서 Each user-level thread created by the application 는 각각 Kernel 로 알려지며, All threads can access the kernel at the same time.

이 방식의 단점은, 지원되는 스레드의 수가 제한된다는 점이다.

Native Threads - Many to Many Model

Many user-level threads to Many kernel-level threads(Many to Many Model) 는 1:1 Model 의 제한을 피한다.

JavaApplication 은 Process 를 너무 무겁게 만들지 않을 정도의 스레드를 가질 수 있다.

The standard way of implementing multi-tasking in Java is to use threads. The standard threading model in Java, covering all JVM languages, uses native threads. This has been the case since Java 1.2 and is the case regardless of the underlying system that the JVM is running on.

Native Threads directly map to threads of execution on the computer CPU – and the operating system manages the mapping of threads onto CPU cores.

Lightweight Process

위 Figures 를 살펴보면 LWP(Light Weight Process) 라는 개념이 등장하는데, 쉽게 말해 JavaThreads 와 KernelThreads 를 매핑해주는 역할을 한다고 보면된다. Intermediate Layer 이다.

Lightweight Processes:

The threads library uses underlying threads of control called lightweight processes that are supported by the kernel. You can think of an LWP as a virtual CPU that executes code or system calls.

Automatic concurrency control for unbound threads. The threads library dynamically expands and shrinks the pool of LWPs to meet the demands of the application. All Java threads are unbound by default. Unbound user-level threads defer control of their concurrency to the threads library, which automatically expands and shrinks the pool of LWPs to meet the demands of the application's unbound threads.

Scheduling

Each LWP is a kernel resource in a kernel pool, and is allocated (attached) and de-allocated (detached) to a thread on a per thread basis.

Scheduling 문서에 설명이 잘 나와있다. 기본적으로 대부분의 Thread 는 unbound 상태이며, LWP Pool 에서 사용 가능한 LWP 와 Bound 될 수 있도록 User space 공간에서 예약된다. Unbound threads are created PTHREAD_SCOPE_PROCESS.

Thread 가 LWP 와 Bound 되면 Bound Thread 라고 하며 System Scope 에 속한다.

Java Native Interface

자바 네이티브 인터페이스(Java Native Interface, JNI)는 자바 가상 머신(JVM)위에서 실행되고 있는 자바코드가 네이티브 응용 프로그램(하드웨어와 운영 체제 플랫폼에 종속된 프로그램들) 그리고 C, C++ 그리고 어샘블리 같은 다른 언어들로 작성된 라이브러리들을 호출하거나 반대로 호출되는 것을 가능하게 하는 프로그래밍 프레임워크이다.

JNI Interface Functions and Pointers:

A VM implementing the JNI may allocate and store thread-local data in the area pointed to by the JNI interface pointer.

파일 읽기 및 쓰기, 네트워크 통신 같은 기능을 사용하기 위해서는 OS 에게 작업을 요청을 해야하는데 system call 을 통해 요청하게 된다. 자바에서 system call 을 하기 위해서는 보통 C,C++ 같은 Natvie Code 로 작성이 되어있다.

Java 스레드가 JNI 를 통해 Linux 스레드에 매핑되는 방법을 보여주는 작은 데모 APP 해당 GitHub 를 보면 Linux Threads 가 Java Threads 보다 적은 수를 가지고 있음을 알 수 있다.

References