기록하기

프로세스와 스레드, 멀티태스킹 본문

language/java

프로세스와 스레드, 멀티태스킹

jjungdev 2024. 11. 18. 21:12

Java 21 의 Virtual Thread 는 기존의 Java 멀티스레딩 모델을 개선하여 '더 높은 처리량' 과 '효율적인 리소스 활용' 을 가능하게 해주었다고 한다.

여기서 더 높은 처리량이라는 것은, 같은 시간 및 기간이 있을 때 더 많은 일을 수행하는 것을 의미하는데 그 일을 수행하고 처리량을 증대시킨다는 것의 기준이 되는 개념은 프로세스와 스레드라고 생각해서 이 내용을 먼저 정리하고 그 이후에 Virtual Thread 에 대한 내용을 살펴보고자 한다.

 

이미 많은 블로그와 강의에서 잘 정리된 내용들이지만, 스스로 내용 정리를 해보지는 않았어서 이 연재의 첫 시작을 '프로세스와 스레드, 멀티태스킹' 으로 잡았다.

 

  1. 프로세스와 스레드, 멀티태스킹(현재글)

멀티태스킹

하나의 CPU 코어만 있는데도 마치 여러 프로그램이 동시에 실행되는 것처럼 느끼게 하는 즉 시분할 기법을 사용하는 것을 멀티태스킹이라고 한다. 여기서는 일단 이해를 위해 CPU 코어 1개가 있다고 가정했는데, 만약 멀티태스킹이 되지 않는다면 어떤 상황이 일어날까?

 

우리는 현재 음악을 들으면서 지금처럼 블로그를 작성하는 일이 너무 자연스럽다. 하지만 멀티태스킹이 되지 않는다면 아래와 같이 한가지의 일이 즉 한 가지의 프로그램이 다 끝난 뒤에 다른 일을 수행할 수 있을 것이다.

이 2가지의 일이 동시에 수행이 되지 않고 아래와 같이 음악 듣기의 일이 모두 끝난 뒤 블로그 쓰기의 프로그램이 실행될 것이다.

하지만 이대로라면 사용자의 요구사항을 만족시키기도 어렵고 매우 답답한 상황이 지속될 것이다. 그래서 나온 멀티태스킹의 개념은, 실제로는 위에 두 프로그램이 번갈아서 수행하지만 사용자가 보기에는 마치 두 프로그램이 동시에 실행되는 것처럼 느끼게 만드는 기법이다.

아래 그림처럼 각 프로그램이 한번씩 수행이 되고, 그 작업이 0.01초만에 바뀐다면 사용자는 이전과 다르게 하나의 프로그램 작업이 끝날 때까지 기다리지 않아도 된다.

멀티프로세싱

CPU 코어를 1개라고 가정했지만, 현재는 CPU 코어가 1개인 제품은 없을 것이다. 현재 기준으로 새로 나온 맥북은 10코어가 가장 낮은 스펙인데 이를 보더라도 대부분의 노트북은 하나의 CPU 안에 2개 이상의 코어를 가지고 있을 것이다.

 

그렇다면 위 상황에서 CPU 코어가 2개이면 어떻게 프로그램이 실행될까?

이전에는 마치 동시에 실행되는 것처럼 수행이 되었지만, 이제는 실제로 2개의 코어가 존재하기 때문에 2개의 프로그램이 물리적으로 동시에 실행될 수 있다. 즉 멀티프로세싱이란, 2개 이상의 CPU 코어에서 여러 프로그램을 동시에 처리하는 기법을 말한다.

 

위 예제처럼 음악 듣기와 블로그 쓰기를 동시에 하는데 코어가 이제는 1개가 아니라 2개라면 아래와 같이 각 코어에서 프로그램이 실행될 것이다. 따라서 현재는 2개의 프로그램만 실행된다고 가정했으나 멀티프로세싱을 통해 여러 프로그램이 실행될 수 있는 것이다.

하나의 코어에서 시분할 기법으로 동시에 여러 프로그램이 실행되는 것처럼 수행이 되면서(멀티태스킹) + 실제로 이러한 코어가 여러개가 있게 된다면(멀티프로세싱) 더 많은 처리량을 보일 수 있게 된다.

그렇다면 멀티프로세싱이 항상 좋을까?

한 코어 내에서 여러 프로세스가 실행이 되면서 마치 동시에 실행이 되는 것처럼 보이기 위해 시분할 시스템을 이용한다고 했는데 이렇게 다른 프로세스에 CPU 점유를 넘기려면 이전에 어디까지 명령을 수행했고 어떤 변수를 저장했는지에 대한 정보가 필요하다.

이 정보를 context 라고 하는데 이는 PCB 라는 Process Control Block 에 저장이 된다. 이렇게 한 프로세스에서 다른 프로세스로 CPU 제어권이 넘어가는 것을 컨텍스트 스위칭이라고 하는데 다시 PCB 에서 읽어와서 이전에 어디까지 실행이 되었는지 확인하는 절차가 필요하기에 이 역시 비용이 발생하게 된다.

참고로 스레드 역시 마찬가지인데, 스레드를 많이 만들고 서로 스위칭을 하면서 연산을 시킨다면 이 컨텍스트 스위칭 비용이 매우 커지게 될 것이다.

프로세스와 스레드

여기서 예시로 든 음악 듣기와 블로그 쓰기는 각각 프로세스로 이해할 수 있다. 각 프로세스는 독립적이기 때문에 심각한 문제가 발생해도 해당 프로세스만 종료되고 다른 프로세스에는 영향을 주지 않는다.

프로세스란,
OS 안에서 실행중인 프로그램을 말한다.
실행 환경과 자원을 제공하는 컨테이너 역할

 

프로그램이 CPU 에서 실행되려면 메모리에 적재된 상태여야 하는데 이 메모리 공간은 Code, Data, Stack, Heap 4개 영역으로 이루어져 있다.

 

 

  • Code 영역 : 실행한 프로그램의 코드가 저장되는 영역
  • Data 영역 : 전역변수와 static 변수가 저장되는 영역
  • Heap 영역 : 프로그래머가 직접 공간을 할당 및 해제하는 영역
  • Stack 영역 : 지역 변수와 매개 변수가 저장되는 임시 메모리 영역

 

 

 

 

 

 

 

 

 

 

이 프로세스는 하나 이상의 스레드를 반드시 포함하는데 프로세스는 독립적인 메모리 공간을 가지고 있는 것에 반해, 스레드는 동일한 메모리 공간을 공유한다. Code, Data, Heap 은 모든 스레드가 공유하고, Stack 의 경우 자신의 공간을 갖고 있다.

스레드란,
프로세스 내에서 실행되는 작업의 단위이다.
실제로 코드 하나하나 실행하는 것

 

하나의 프로세스 내에 여러 스레드가 있게 되면 멀티스레드 환경이 된다. 이미 멀티태스킹, 멀티프로세싱이 있는데 멀티스레드까지 왜 필요할까 라는 의문이 들수도 있지만, 우리가 하나의 프로세스/프로그램을 실행해도 그 안에 여러 작업이 진행되는 것을 알 수 있다. 예를 들어, 음악을 들을 때도, 음악 재생과 함께 가사도 표시가 되어야 하고, 음악 목록 조회 등이 같이 이루어져야 한다. 따라서 하나의 프로그램 내에서도 여러 작업이 동시에 실행이 되어야 하므로 멀티스레드가 필요한 것이다.

멀티스레드

그렇다면 위 그림에서 이제 각 프로세스 내에 스레드가 2개씩 있다고 가정해보자

이렇게 멀티스레드 환경일 때는 예를 들면, 스레드 A1 작업을 하다가 잠시 멈추고 스레드 A2 작업을 진행하는 식으로 실행이 될 것이다. 만약 CPU 코어가 1개가 아니라 2개라면 실제로 동시에 실행이 되면서 각 스레드 작업이 수행되다가 다른 스레드가 또 실행되다가 하는 일련의 작업이 진행이 된다.

여기서 각 스레드는 스케줄링 큐에서 대기하게 되는데 아래와 같이 대기 중인 스레드가 큐에 쌓여있고, 하나씩 실행하다가 잠시 멈춘 뒤 다른 스레드가 실행이 되면 현재 실행중이었던 스레드를 뒤에 다시 넣는 작업을 반복한다.

만약 멀티프로세싱 환경이라면 즉 CPU 코어가 여러 개인 경우라면 진짜로 동시에 실행이 되면서, 각 스레드 작업이 큐에 쌓이는 형태가 될 것이다. 이는 아래 그림과 같다.

김영한님 강의 내용을 참고해서 프로세스, 스레드, 멀티프로세싱에 대한 개념을 정리해보았다.

다음으로는 Future, ExecutorService 에 대해서 정리를 해보겠다.

 

 

참고
- 김영한님 고급 자바 강의 1

'language > java' 카테고리의 다른 글

try-with-resources 사용법 예시와 AutoCloseable 구현  (0) 2023.09.16
String Constant Pool 과 equals, hashCode  (0) 2023.09.07
Java의 GC 진행 방법  (0) 2023.08.18
List, Set, Map 의 차이  (0) 2022.06.11