-
Thread & Process - 1TIL 2023. 12. 27. 04:55728x90
프로세스와 스레드 개념
프로세스와 스레드에 대한 개념을 이해하기 쉽게 설명하면 다음과 같다:
프로세스 : 운영체제로부터 필요한 자원(메모리, CPU 시간 등)을 할당받아 작동하는, 독립적인 작업의 단위
스레드 (Thread): 프로세스 내에서 프로세스가 할당받은 자원을 사용하는 개별적인 실행 흐름의 단위
프로그램과 프로세스
정적 프로그램
프로그램은 실행 가능한 파일의 형태로 존재하는 코드의 집합이다. 예를 들어, 윈도우의 .exe 파일과 같은 형태로 저장되며, 아직 실행되지 않은 상태다.
프로세스
프로그램이 실행되면 프로세스가 됩니다. 이는 운영체제로부터 메모리와 CPU 자원을 할당받아 동적으로 실행되는 프로그램의 인스턴스다. 같은 프로그램이라도 여러 프로세스로 실행될 수 있다.
모든 프로그램은 운영체제가 메모리 공간을 할당해 주어야 실행될 수 있다. 그래서 프로그램을 실행하는 순간 파일은 컴퓨터의 메모리에 올라가고, 운영체제로부터 CPU 자원을 할당받아 프로그램 코드를 실행시켜 서비스를 이용할 수 있게 된다.
똑같은 애플리케이션의 실행 유무의 차이를 가지지만 엄밀히 다른 정의를 가진다.
스레드
프로세스의 한계
프로그램을 실행할 때 프로세스 하나만을 사용해서 이용할 경우 한계를 가진다. 파일을 다운받으면 실행 시작부터 실행 끝까지 프로세스 하나만을 사용하기 때문에 다운이 완료될 때까지 하루종일 기다려야 했다.
동일한 프로그램을 여러 개의 프로세스로 만들면 그만큼 메모리를 차지하고 CPU에서 할당 받는 자원이 중복되게 된다.
스레드의 개념
하나의 프로세스 내에서 동시에 진행되는 작업 흐름의 단위
크롬이 실행되면 프로세스 하나가 생성이 된다. 하지만 크롬 브라우저에서 게임도 하고 음악도 들을 수 있다. 이는 곧 하나의 프로세스 안에서 여러 가지 작업 흐름이 동시에 진행되기 때문에 가능한 것.
이 일련의 작업들을 스레드라고 하며, 여러 개가 있다면 이를 멀티 스레드라고 한다.
하나의 프로세스 안에 여러 개의 스레드 들이 들어있을 수 있으며, 스레드가 많을수록 프로그램 속도도 동시에 하는 작업이 많아지기 때문에 성능이 올라갈 수 있다. 단 스레드를 많이 사용하면 동시에 여러 작업을 처리할 수 있지만, 스레드 관리 및 컨텍스트 스위칭에 따른 오버헤드도 고려해야 한다.
일반적으로 하나의 프로그램은 하나 이상의 프로세스로 구성될 수 있으며, 하나의 프로세스는 하나 이상의 스레드를 갖는다.

프로세스 & 스레드의 메모리
프로세스의 자원 구조
프로그램이 실행되어 프로세스가 만들어지면 다음 4가지의 메모리 영역으로 구성되어 할당받게 된다.

- 코드 영역 : 프로그래머가 작성한 프로그램의 실행 코드가 CPU가 해석 가능한 기계어 형태로 저장. 프로그램의 함수와 명령어들이 이 영역에 위치한다.
- 데이터 영역 : 코드가 실행되면서 사용하는 전역 변수나 데이터(.data, .rodata, .bss)들이 모여있다.
- .data : 초기화된 전역 변수나 정적 변수가 저장된다.
- .bss : 초기화되지 않은 전역 변수나 정적 변수가 저장된다.
- .rodata : const 같은 상수 키워드로 선언된 변수나 문자열 상수가 저장
- 스택 영역 : 함수의 호출과 함께 할당되고, 호출이 끝나면 소멸되는 지역 변수와 함수의 실행 정보가 저장된다. 스택 영역을 초과하면 stack overflow 에러가 발생한다.
- 힙 영역 : 동적으로 할당되는 데이터(예: 객체, 배열)가 저장되는 곳이다. 프로그래머에 의해 메모리 공간이 동적으로 할당되고 해제된다.
스택 영역과 힙 영역은 프로세스가 실행되는 동안 크기가 조절되는 동적 영역이다.
프로그램이 실행될 때, 메모리에 프로세스 별로 고유의 주소 공간이 할당되며, 이 안에 코드, 데이터, 스택, 힙 영역이 구성된다.
프로세스 마다 이러한 메모리 구조가 독립적으로 생성되어 각각의 실행 환경을 유지한다.

스레드의 자원 공유
스레드는 프로세스가 할당받은 자원을 이용하는 실행 단위다. 멀티스레딩 환경에서는 파일 다운로드와 같은 작업을 진행하는 동안에도 다른 스레드를 통해 웹 서핑과 같은 다른 작업을 동시에 수행할 수 있다. 이는 이는 스레드가 프로세스의 자원(코드, 데이터, 힙)을 공유하면서 동시에 여러 작업 흐름을 가능하게 하기 때문이다.
따라서 아래와 같이 하나의 프로세스 내에 여러 개의 스레드가 들어있는 상태가 된다.

이때 프로세스의 4가지 메모리 영역(코드, 데이터, 힙, 스택) 중 스레드는 각각 독립적인 스택을 가집니다. 이 스택에는 함수 호출 정보, 지역 변수 등이 저장된다. 반면, 코드 영역, 데이터 영역, 그리고 힙 영역은 프로세스 내의 모든 스레드에 의해 공유된다.
따라서 각각의 스레드는 별도의 스택을 가지고 있지만 힙 메모리는 고유하므로 서로 다른 스레드에서 가져와서 읽고 쓸 수 있다.

스택은 함수가 호출될 때 전달되는 인자, 되돌아갈 주소값, 함수 내에서 선언하는 변수 등을 저장하는 메모리 공간이다.
스레드가 독립적인 스택을 가진다는 것은, 각 스레드가 자신만의 함수 호출 스택과 실행 컨텍스트를 가진다는 의미다. 이로 인해 각 스레드는 독립적인 실행 흐름을 가질 수 있다.
반면에 프로세스는 기본적으로 프로세스 간에 다른 프로세스의 메모리에 직접 접근할 수 없다.
프로세스의 자원 공유
기본적으로 각 프로세스는 메모리에 별도의 주소 공간에서 실행된다. 따라서 다른 프로세스의 변수나 자료구조에 접근할 수는 없다.
특별한 방법을 통해 프로세스가 다른 프로세스의 정보에 접근하는 것이 가능하다. 프로세스 간 정보를 공유하는 방법에는 다음과 같은 방법들이 있다.
- IPC 사용
- LPC 사용
- 별도로 공유 메모리를 만들어서 정보를 주고 받도록 설정.

하지만 프로세스 간의 자원 공유는 단순히 CPU 레지스터 교체뿐만 아니라 RAM과 CPU 사이의 캐시 메모리 까지 초기화 되기 때문에 자원 부담이 크다는 단점이 있다.
- 이 과정에서 RAM과 CPU 사이의 캐시 메모리도 영향을 받는다. 캐시는 빠른 데이터 접근을 위해 최근 사용된 데이터를 저장하는데, 프로세스가 전환되면 새로운 프로세스에 필요한 데이터로 캐시를 새롭게 채우기 위해 기존 캐시 내용을 초기화하거나 변경해야 한다.
- 프로세스 간의 자원 공유에 관련된 부담은 주로 컨텍스트 전환(context switch)에서 발생한다. 프로세스가 전환될 때, 운영체제는 현재 실행 중인 프로세스의 상태(예: CPU 레지스터 값, 프로그램 카운터)를 저장하고, 다음 프로세스의 상태를 CPU에 로드해야 한다.
따라서 다중 작업을 처리할 때, 스레드를 사용하는 것이 메모리와 컨텍스트 전환 비용 측면에서 프로세스보다 효율적이다.
현대 컴퓨터의 운영체제는 멀티 프로세스를 지원하지만 멀티 스레딩을 기본으로 하여 더 효율적인 자원 사용과 빠른 컨텍스트 전환을 가능하게 한다.
프로세스 & 스레드의 동시 실행 원리
음악을 들으면서 웹서핑을 할 수 있는 이유는 컴퓨터 내부적으로 프로세스와 스레드를 동시에 처리하는 멀티 태스킹기술 떄문이다.
이때 동시에 처리하는 기술적 원리가 운영체제 이론의 핵심 원리다.
멀티 코어와 스레드
CPU 한 개는 여러 개의 코어를 가질 수 있다. 코어는 말 그대로 CPU 코어 유닛이다. 즉 명령어를 메모리에서 뽑아 해석하고 실행하는 반도체 유닛이다.
현대의 CPU는 여러 개의 코어를 가지고 있으며, 각 코어는 독립적인 명령어 처리 단위다. 코어가 많을수록 동시에 처리할 수 있는 작업의 수가 증가한다.
스레드는 논리적 코어 갯수를 의미한다.
4코어 8스레드는 물리적 코어 하나가 스레드 2개 이상을 동시에 실행 가능하다는 의미이고 곧 운영체제가 8개의 작업을 동시에 처리할 수 있게 된다. ⇒ 하이퍼스레딩 기술
CPU의 스레드는 하드웨어적 스레드(물리적으로 CPU에 구현된 스레드)를 의미하며, 프로그램의 스레드는 소프트웨어적 스레드(프로그램 내에서 생성되는 실행 흐름)를 의미한다.
수십 수백개의 프로세스를 처리하는 방법이 가능한 원리를 이해하기 위해서는 병렬성과 동시성이라는 개념을 알아야 한다.
CPU의 작업 처리 방식
병렬성
직관적으로 명령어를 메모리에서 확인해서 해석하고 실행하는 반도체 유닛인 코어에 맞춰 프로세스, 스레드를 돌려 병렬로 작업들을 동시에 수행하는 것이다.
듀얼코어, 쿼드코어, 옥타코어 등의 멀티코어 프로세서는 각 코어가 독립적으로 작업을 처리함으로써 물리적인 병렬 처리를 가능하게 한다.

동시성
동시성은 여러 작업이 번갈아 가며 실행되어 동시에 수행되는 것처럼 보이게 하는 것이다. 컴퓨터는 프로세스나 스레드를 매우 빠르게 전환하면서 동시에 작업하는 것처럼 보이게 한다.
작업들을 번갈아가면서 실행할 때, 각 작업들을 매우 조금씩만 수행하고, 다음 작업으로 넘어가는 식으로 동작한다. 이렇게 여러 작업들을 동시에 처리하는 것처럼 보이게 만들어서 사용자에게 더 빠른 반응성을 제공한다.
이 과정에서 일어나는 작업 전환을 '컨텍스트 스위칭(Context Switching)'이라고 한다.
동시성이 필요한 이유
동시성은 결국 동시에 돌아가는 것처럼 보이는 것이고 실제로 동시에 돌아가는 것이 아니므로 최종 작업 시간은 거의 차이가 없을 것이다.
하지만 병렬적으로 처리하지 않고 작업들을 스위칭하는 이유는 다음과 같다.
- 하드웨어적 한계 : 현대의 CPU는 코어 수를 늘려 성능을 향상시키고 있지만, 무한정 코어 수를 늘릴 수는 없다. 따라서 수십, 수백 개의 프로세스나 스레드를 효율적으로 관리하기 위해 동시성이 필요하다.
- 논리적 효율성 : 4코어 8스레드 CPU 환경을 가정했을 때 총 16개의 작업을 수행하고 이중 8개는 오래 걸리는 작업, 나머지 8개는 짧게 끝나는 작업이라고 가정할 때, 병렬적으로 처리하면 최대 8개까지 동시에 처리한다. 최악의 경우 오래 걸리는 8개의 작업을 먼저 동시에 처리한다고 하면 남은 8개의 작업은 빨리 처리할 수 있음에도 처리 중인 8개의 작업이 끝날 때까지 기다려야 한다. 이런 비효율성을 개선하기 위해 동시성 개념을 채택한다.
동시성은 물리적인 병렬 처리 능력을 넘어서는 소프트웨어적인 효율성을 제공한다. 이를 통해 하드웨어 자원을 최대한 활용하여 더 많은 작업을 효과적으로 처리할 수 있게 해준다.
따라서 병렬적으로 동시적으로 작업을 하면서 그보다 많은 소프트웨어적 스레드가 있다면 적절히 병렬성과 동시성을 섞어 동시에 돌리게 된다.
728x90'TIL' 카테고리의 다른 글
Thread & Process - 2 (1) 2023.12.28 Docker로 개발환경을 구축하는 이유 (0) 2023.12.27 [TIL] 재귀 함수 결과 캐시 : functools.cache - 리트코드 338 (0) 2023.12.21 set 자료구조를 활용하여 조건 검사 속도 최적화 - 리트코드 345 (0) 2023.12.18 1. Two Sum 공간복잡도 O(1)로 풀어보자.. (0) 2023.12.13