TanzDev

TIL 44 (프로세스와 쓰레드) 본문

기록보드/TIL

TIL 44 (프로세스와 쓰레드)

Tanz-dev 2024. 3. 21. 16:18

프로세스와 스레드(Process vs Thread)

프로세스와 스레드는 면접볼때 높은 확률로 나오는 문제라고 하기에 꼭 집고 넘어가야할거같았기때문에

따로 정성과 땀과 열정을 쏟아 작성해보도록 하자.

 


📌  프로세스 :운영체제로부터 자원을 할당받은 작업의 단위

📌  스레드 :프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위

 

 

프로세스🏡 : 자신만의 고유 공간과 자원을 할당받아 사용

  • 프로세스는 메모리 상에서 실행중인 프로그램을 말하며, 쓰레드는 이 프로세스 안에서 실행되는 흐름 단위
  • 프로세스는 최소 하나의 쓰레드를 보유하고 있으며, 각각 별도의 주소공간을 독립적으로 할당(code, heap, stack)
  • “컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램”
  • 메모리에 올라와 실행되고 있는 프로그램의 인스턴스(독립적인 개체)
  • 운영체제로부터 시스템 자원을 할당받는 작업의 단위
  • 즉, 동적인 개념으로는 실행된 프로그램을 의미한다.

 

  • 참고 할당받는 시스템 자원의 예
  • CPU 시간
  • 운영되기 위해 필요한 주소 공간
  • Code, Data, Stack, Heap의 구조로 되어 있는 독립된 메모리 영역

 

 

 

프로세스는 다음의 특징을 갖습니다.

  • 각각 독립된 메모리 영역(Code, Data, Stack, Heap)을 할당받습니다.
    • 코드 영역(code area): 프로그래머가 작성한 프로그램이 저장되는 영역
    • 데이터 영역(data area): 코드가 실행되면서 사용한 환경이나 파일들의 각종 데이터들이 모여있습니다.
    • 스택 영역(stack area): 호출한 함수가 종료되면 되돌아올 메모리의 주소나 지역 변수 등이 저장됩니다.
    • 힙 영역(heap area): 동적으로 할당되는 데이터를 위해 존재합니다.
  • 최소 1개 이상의 스레드(메인 스레드)를 가지고 있다.
  • 각 프로세스는 별도의 주소 공간에서 실행되며 기본적으로 다른 프로세스의 자원에 접근할 수 없다.
  • 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간 통신(IPC)를 사용해야 한다.
    • ex. 파이프, 파일, 소켓 등을 이용한 통신 방법
  • 그림에서 여러 프로세스가 동시에 실행되고 관리 되는 것 처럼 보인다. 하지만 CPU는 한 번에 한 가지 명령밖에 처리할 수 없다. 즉, 동시가 아니라 빠르게 프로세스들을 번갈아가면서 실행하고 관리하고 있는 것이다.

 

 

프로세스 만으로 작업을 처리할때의 문제점

  • 프로세스 생성에 큰 오버헤드가 존재
    • 프로세스를 생성할때 많은 시간이 소요됨
  • 프로세스 컨텍스트 스위칭의 비효율성, 오버헤드가 큼
  • 프로세스 사이에 통신이 어렵고,
    • 비용이 비싼 IPC 사용해서 통신을 합니다. (또는 LPC, 공유 메모리)

 

IPC(Inter-Process Communication)는 프로세스간 통신을 위한 메커니즘입니다. 프로세스 간 데이터를 주고받기 위한 방법으로, Message Queue, Shared Memory, Semaphore, Socket 등의 방법이 있습니다.

 

 

 

 

쓰레드 : 다른 쓰레드와 공간과 자원을 공유하면서 사용

  • 쓰레드는 프로세스안에서 작업을 처리하는 주체
  • 쓰레드는 자원 중에 stack 만 따로 할당받고 나머지 영역은 쓰레드끼리 서로 공유

스레드는 다음의 특징을 갖습니다.

  • 프로세스 내에서 각 필요한 Stack만 할당받고 Code, Data, Heap 영역은 공유해서 각 스레드가 공유합니다.
  • 같은 프로세스 내 스레드끼리 자원(Heap 등)을 공유하며 실행됩니다.
    • 즉, 스레드는 공유하는 자원인 Heap 영역에 있는 변수를 수정할 수 있습니다.
  • 프로세스 하나만을 사용해서 프로그램을 실행하기에는 메모리의 낭비가 발생합니다.
    • 레드는 프로세스와 다르게 스레드 간 메모리를 공유하며 작동합니다.
    • 즉, 프로세스가 할당받은 자원을 이용하는 **처리 작업(실행의 흐름)**의 단위 입니다.

쓰레드가 해결한 문제들

  • 프로세스 보다 크기가 작은 실행 단위 구현
  • 프로세스의 생성 및 소멸에 따른 오버헤드 감소
  • 쓰레드간 자원을 공유 함으로써 빠른 컨텍스트 스위칭
  • 프로세스 들의 통신 시간, 방법 어려움 해소

프로세스와 쓰레드 비교

  • 운영체제는 프로세스마다 독립된 메모리 영역을 Code/Data/Stack/Heap의 형식으로 할당합니다.
    • 각각 독립된 메모리 영역을 할당해주기 때문에 프로세스는 다른 프로세스의 변수나 자료에 접근할 수 없습니다.
  • 이와 다르게, 스레드는 메모리를 서로 공유할 수 있습니다.
    • 프로세스가 할당받은 메모리 영역 내에서 Stack 형식으로 할당된 메모리 영역은 따로 할당받고, 나머지 Code/Data/Heap 형식으로 할당된 메모리 영역을 공유합니다.
    • 따라서, 각각의 스레드는 별도의 스택을 가지고 있지만 힙 메모리는 서로 읽고 쓸 수 있게 됩니다.
    • 즉, 치킨집에서 각자 일하는 공간이 있지만, 같이 보는 업무 가이드(Code)가 있고, 주문도 같이 받고(Data), 손님이 오고가는 홀 공간도 같이 쓴다(Heap)는 점과 비슷합니다.

 

 

정리하자면,

  • 프로세스는 운영체제로부터 별도의 메모리 영역을 할당 받고
  • 스레드는 Stack 을 제외한 Code/Data/Heap 부분은 공유해 서로 읽고 쓸 수 있다 (공유자원)

 

멀티스레드와 멀티프로세스

 

 


📌요약

쓰레드는 운영체제의 스케줄러에 의해 독립적으로 관리될 수 있는 프로그래밍된 명령어의 가장 작은 흐름 입니다. 하나의 프로세스는 하나 이상의 쓰레드를 갖고 있습니다.

멀티 프로세스 : 하나의 운영체제 안에서 여러 프로세스가 실행되는 것

멀티 쓰레드 : 하나의 프로세스가 여러 작업을 여러 쓰레드를 사용해 동시에 처리하는 것

 

스레드 풀

(스레드들의 수영장)

 

  • 컴퓨터 프로그래밍에서 쓰레드 풀은 컴퓨터 프로그램에서 실행의 동시성을 달성하기위한 소프트웨어 디자인 패턴입니다.
  • 프로그램이 작업을 동시에 실행할 수 있도록 여러 스레드를 미리 생성해두고 유지 관리합니다.
  • 여러 Thread를 동시에 만들어 실행(병렬처리)할 수 있습니다.
  • 그렇다고 해서 Thread를 계속 늘려가는 건 좋은 것 일까?
    • 당연히 아닙니다. 하드웨어의 제한적인 사항(CPU, Memory 등)이 있기 때문에 관리할 필요가 있습니다. 그래서 쓰레드 풀 이라는 개념을 이용합니다.
  • 쓰레드 풀은 작업 처리에 사용되는 쓰레드를 제한된 개수만큼 정해 놓고 작업 큐(Queue)에 들어오는 작업들을 하나씩 쓰레드가 맡아 처리하는 것을 말합니다.
    • 치킨집에서 직원 뽑기가 어려우니 직원들을 미리 뽑아두는 것과 비슷합니다.
    • 해야할 일을 순서대로(작업 큐) 직원들에게 할당 해주며 처리하도록 합니다.

스레드 풀의 동작

1. 초기화: 쓰레드 풀을 사용하기 전에 초기화해야 합니다. 이 단계에서는 쓰레드 풀의 크기, 최대 쓰레드 수, 작업 큐 등의 매개변수를 설정합니다.

2. 작업 수신: 쓰레드 풀은 작업을 수신하고 처리할 준비를 합니다. 작업은 일반적으로 작업 큐에 추가됩니다.

3.작업 수행: 쓰레드 풀에서는 미리 생성된 쓰레드들이 작업 큐를 모니터링하고 대기 중인 작업을 가져와 처리합니다. 이때 쓰레드 풀 내의 쓰레드들은 일반적으로 무한 루프를 돌면서 작업을 가져오기 위해 대기합니다.

4. 작업 처리: 쓰레드 풀의 스레드가 작업을 가져와서 처리합니다. 작업은 일반적으로 작업 큐에서 FIFO(선입선출) 방식으로 가져오게 됩니다.

5. 작업 완료 및 반환: 작업이 완료되면 해당 결과를 반환하고, 쓰레드는 다시 작업 큐에서 새로운 작업을 가져오기 위해 대기 상태로 돌아갑니다.

6. 작업 대기: 작업 큐에 새로운 작업이 추가되면 쓰레드 풀의 스레드들은 대기 상태를 벗어나 작업을 가져와 처리합니다. 이를 반복하여 계속적으로 작업을 수행합니다.

7. 종료: 쓰레드 풀을 더 이상 사용하지 않을 때 종료합니다. 종료할 때는 모든 작업이 완료되었는지 확인하고, 필요에 따라 남은 작업들을 처리하거나 버릴 수 있습니다.

 

스레드 풀을 사용하는 이유 

1. 프로그램 성능 저하를 방지하기 위해

  • 매번 발생하는 작업을 병렬처리하기 위해 쓰레드를 생성/수거하는 데 따른 부담은 프로그램 전체적인 퍼포먼스를 저하시키기때문에, 쓰레드풀을 만들어 놓고 사용함
  • 쓰레드 또한 프로세스가 할당한 메모리를 사용합니다.
  • 즉, Java의 경우 쓰레드를 생성하면 JVM 메모리를 소비하게 되는 것이다. 쓰레드 자체도 레지스터와 스택을 가지고, 쓰레드도 컨텍스트 스위칭이 일어나기 때문에 쓰레드 생성에 따른 메모리 할당을 무시할 수 없습니다.

2. 다수의 사용자 요청을 처리하기 위해

  • 대규모 프로젝트에서 특히 중요
  • 다수의 사용자의 요청을 수용하고, 빠르게 처리하고 대응하기 위해 쓰레드풀을 사용합니다.
  • 특히 Bottle Neck 현상이 발생하는 I/O 작업과 데이터베이스 작업에서 주로 사용됩니다.
  • 쓰레드가 아무리 빠르게 생성되더라도 시스템 스케줄러에서 쓰레드의 우선순위를 매번 할당해야 하는데, 쓰레드풀을 이용하면 일정 쓰레드가 이미 생성되기 때문에 쓰레드풀에 의해 라이프 사이클이 관리되고, 쓰레드 풀에 의해 작업이 큐를 이용하게 되어 우선순위가 배분되고 처리됩니다.

쓰레드 풀의 장점

  • 쓰레드를 생성/수거하는데 비용이 들지 않습니다.
  • 쓰레드가 생성될 때 OS가 메모리 공간을 확보해주고 메모리를 쓰레드에게 할당해줍니다.
  • 쓰레드 풀을 미리 만들어 두기 때문에 처음에 생성하는 비용은 들지만 이전의 쓰레드를 재사용할 수 있으므로 시스템 자원을 줄일 수 있고, 작업을 요청 시 이미 쓰레드가 대기 중인 상태이기 때문에 작업을 실행하는 데 딜레이가 발생하지 않습니다.

쓰레드 풀의 단점

  • thread pool에 thread를 너무 많이 생성해 두었다가 사용하지 않으면 메모리 낭비가 발생합니다.
  • Thread pool의 단점 개선 : Fork Join Thread Pool

동시성(Concurrency)과 병렬성(Parallelism)

동시성

싱글 코어에서 멀티 스레드를 동작시키기 위한 방식으로 멀티 태스킹을 위해 여러 개의 스레드가 번갈아가면서 실행되는 성질을 말합니다. 동시성을 이용한 싱글 코어의 멀티 태스킹은 각 스레드들이 병렬적으로 실행되는 것처럼 보이지만 사실은 번갈아가면서 조금씩 실행되고 있는 것입니다.

병렬성

멀티 코어에서 멀티 스레드를 동작시키는 방식으로, 한 개 이상의 스레드를 포함하는 각 코어들이 동시에 실행되는 성질을 말합니다. 병렬성은 데이터 병렬성(Data parallelism)과 작업 병렬성(Task parallelism)으로 구분됩니다.

  • 데이터 병렬성

데이터 병렬성은 전체 데이터를 쪼개 서브 데이터들로 만든 뒤, 서브 데이터들을 병렬 처리하여 작업을 빠르게 수행하는 것을 말합니다.

자바8에서 지원하는 병렬 스트림이 데이터 병렬성을 구현한 것입니다.

서브 데이터는 멀티 코어의 수만큼 쪼개어 각각의 데이터들을 분리된 스레드에서 병렬 처리합니다.

  • 작업 병렬성

작업 병렬성은 서로 다른 작업을 병렬 처리하는 것을 말합니다.

대표적인 예는 웹 서버로, 각각의 브라우저에서 요청한 내용을 개별 스레드에서 병렬로 처리합니다.

 

📌 스레드 풀 요약

작업 처리에 사용되는 쓰레드를 제한된 개수만큼 정해 놓고, 작업 큐에 들어오는 작업들을 하나씩 쓰레드가 맡아 처리하는 기법

 

'기록보드 > TIL' 카테고리의 다른 글

TIL 46 (Django)  (0) 2024.03.25
TIL 45 (DB 구조와 유형)  (1) 2024.03.22
TIL 43 (CS 프로세스 생성주기)  (0) 2024.03.20
TIL 42 (CS 스케쥴링)  (0) 2024.03.20
TIL 41 (CS)  (0) 2024.03.18