프로세스와 스레드

프로세스

💡

프로세스란?

프로그램을 실행 하여 메모리에 올라온 상태로 운영체제 안에서 실행중인 프로그램을 프로세스라고 한다.

프로세스는 프로세스 고유의 메모리 구성을 통해 독립적으로 동작한다.

  • 프로세스는 하나 이상의 스레드를 반드시 포함한다.

프로세스의 메모리 구성

멀티 태스킹

프로세스는 개별 실행 프로그램이 현재 실행되어 메모리에 올라온 상태라고 했을 때, 여러 개의 프로그램을 동시에 실행하게 된다면 순차적으로 종료될 때 까지 기다렸다가 실행하지 않는다.

운영체제는 스케줄링에 의해 실행 시켜야 할 프로세스를 굉장히 빠른 속도로 작업 단위를 번갈아가며 동시에 여러 작업을 수행하는 것 처럼 실행 시킨다.

이로써 사용자는 여러 프로그램을 동시에 이용하는 것 처럼 느낄 수 있게 되었지만, 프로세스가 가지고 있는 고유의 데이터 영역을 모두 기억하여 불러와야하는 컨텍스트 스위칭 과정이 많이 발생하게 된다.

이 때, 프로세스가 가지고 있는 정보를 PCB(Process Control Block) 이라고 하며 프로세스를 가르키는 고유의 정보들을 담고 있다가 서로 컨텍스트 스위칭이 진행될 때 이 PCB 를 참조하게 된다.

멀티 프로세싱

CPU 코어가 제한적일 때 최대 효율을 내기 위해 멀티 태스킹 전략을 사용했지만, 사용자는 불편함을 느끼고 기술은 나날이 발전하여 물리적 코어 갯수를 늘리게 된다.

결론적으로 프로세스 여러개를 한 개의 코어에서 짧게 여러 프로세스를 아주 작은 단위로 나누어 실행 하며 컨텍스트 스위칭에 단점을 개선하고자, 물리적으로 여러 개의 코어를 두어 개별 코어가 병렬적으로 프로세스를 하나씩 실행 시키도록 구성한다.

물리적 코어가 개별 프로세스를 실행 하면, 프로세스 간 자원을 공유 해야하는 상황이 발생할 수 있다.

예를 들어 인터넷 브라우저에 탭을 여러개 띄웠는데 개별 탭이 하나의 프로세스로 동작한다고 했을 때 서로 띄워둔 탭 간의 정보를 공유하고 싶을 수 있을 것이다.

프로세스는 메모리 구성이 독립적이기 때문에 서로의 메모리 영역을 접근할 수 없어 자원을 주고 받기 위해 IPC 라는 통신 매커니즘으로 데이터를 주고 받는다.

스레드

💡

스레드란?

프로세스가 독립적인 자원을 할당 받아 코드 덩어리를 한 줄씩 실행하는 작업의 단위를 스레드라고 부른다.

스레드는 프로세스의 메모리 구성 중 코드, 데이터, 힙 영역을 공유하여 사용한다.

데몬 스레드

💡

데몬 스레드란?

백그라운드로 동작하는 스레드이며, 데모나이즈 과정에서 포크한 메인 스레드가 종료되면 같이 종료되는 것이 특징이다.

스레드의 메모리 구성

스레드 컨트롤 블럭

스레드는 개별적으로 인지할 수 있도록 자신만의 고유한 속성 값들이 존재한다. 이 정보들을 바탕으로 어떤 스레드가 어디까지 작업을 실행 했는지, 현재 어떤 상태인지 등을 커널 수준에서 제어할 수 있게 된다.

스레드 속성

  • ID 와 이름
  • 우선순위: 높음, 보통, 낮음
  • 상태: 생성, 실행, 대기, 종료
  • 관계: 그룹

스레드는 CPU 자원을 사용하기 위해 대기열에 배치 되어 할당 받기를 기다리고 있는데 이 때, 어떤 스레드가 먼저 CPU 를 먼저 사용할지 배정받는지를 결정하는 것이 스레드 속성에서 “우선순위” 를 사용한다.

스레드는 어떻게 동작할까?

OS 스케줄러에 의해 아주 짧은 시간동안 CPU 코어를 점유하는 방식으로, 스레드가 여러개일 경우 이를 번갈아가며 사용한다.

스케줄러는 대기줄에 기다리고 있는 스레드가 대기 상태이거나, 블락 상태인 경우 우선순위 규칙에 따라 다음 수행할 스레드를 실행한다.

유저 스레드와 커널 스레드

💡

유저 스레드

유저 스레드는 OS의 유저 모드에서 생성 및 관리 되는 스레드로, 주로 라이브러리를 통해 생성되는 스레드를 일컫는다.

  • 자바에서 과거 GreenThread 나 현재의 VirtualThread 가 이에 속한다.

유저 스레드의 특징

💡

커널 스레드

커널 스레드는 OS 가 지원하는 시스템 레벨의 기능을 지원 받으며 커널이 스레드의 생성 및 스케줄 등을 관리하는 스레드이다.

  • 모든 프로세스는 1 개 이상의 커널 스레드를 할당 받는다.

커널 스레드의 특징

멀티 스레드

프로세스는 무조건 한 개 이상의 스레드를 보유하고 있다고 하였다. 그럼, 프로세스의 스레드가 여러 개로 구성되어 실행 된다면 어떨까?

  1. 프로세스가 운영체제로부터 할당 받은 메모리 영역을 공유할 수 있게된다. 여기서 공유하는 메모리 영역은 코드, 데이터, 힙 영역이다.
  2. 개별 스레드가 보유하고 있는 스택만 새로 할당되기 때문에 멀티 프로세스에 비해 기억해야 할 정보의 양도 적고, 저장해야 할 메모리 영역도 줄어들어 성능상 이점이 있다.

말만 들었을 때 멀티 스레드는 굉장히 좋은 프로세스 관리 방식일 거라 생각이 들지만, 자원을 공유하는 특징에 대한 단점이 존재한다.

💡

스레드의 컨텍스트 스위칭

스레드는 OS 스케줄링에 의해 CPU 코어를 사용하여 논리적 흐름을 실행시킨다.

스레드가 짧은 연산을 마치고 다른 스레드가 연산을 하게 되는 경우 현재 진행 중이던 스레드는 일시 정지 되며 현재 상태의 정보를 백업 하고 있다가, 다시 자신의 차례가 되어 연산을 이어가게 되는 경우 백업해 둔 정보를 복원한다.

  • 스레드의 현재 상태를 백업하는 정보는 CPU 의 레지스터 값이다.

결론적으로 멀티 스레드를 “잘” 사용 하려면 공유하는 자원을 서로 쓰는 행위가 많지 않아야 동시성 이슈를 최소화할 수 있게된다.

멀티 스레드는 왜 필요할까?

CPU 의 발전으로 인해 다중 코어 환경에서 자원을 효율적으로 사용하기 위함이다.

초기에는 CPU 코어가 발전하면서 클럭 속도가 점차 증가하여 연산을 빠르게 할 수 있게 되었다. 하지만, 증가하다보니 더 이상 발전할 수 없는 한계에 봉착했다.

이 한계를 돌파하기 위한 묘수는 클럭 속도가 아닌 코어 갯수를 늘리는 것으로 선택 했고, 여러개의 코어가 뒷받침 되는 환경에서 더 효율적으로 쓸 수 있기 때문이다.

만약, 클럭 속도만 무수히 빠른 코어 1개 와 조금 느리지만 준수한 속도의 코어 여러개가 있다면 어떤 것을 선택할까?

클럭 속도가 빠르다고 무조건 빠를 것이라는 보장을 할 수없다. 컴퓨터라는 복합적인 기기 내부에는 다양한 주변기기가 존재하고, 그 주변기기 또한 연산을 필요로하기 때문이다.

화면에 그래픽을 표현 해주는데 메모리에 디스플레이 비트 값을 담고 있다가 뿌려줘야하고, 키보드 입/출력 또한 마찬가지인데 이러한 연산이 무수히 빠른 코어의 클럭속도를 따라가지 못할 만큼 느리기 때문이다.

스레드 여러개를 사용하면 다른 스레드에서는 대기 시간이 긴 작업을 맡고, 또 다른 스레드에서 연산이 필요한 흐름을 이어갈 수 있다.

참고 자료


baeldung.com
https://www.baeldung.com/cs/user-thread-vs-kernel-threads
kspsd.tistory.com
https://kspsd.tistory.com/50
techblog.woowahan.com
https://techblog.woowahan.com/15398/
inflearn.com
https://www.inflearn.com/course/%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EA%B3%A0%EA%B8%89-1
inflearn.com
https://www.inflearn.com/course/%EB%8F%85%ED%95%98%EA%B2%8C-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-java-part3-1/dashboard