쓰레드는 프로세스와 어떤 차이가 있는가

  • 프로세스와 쓰레드는 자주 비교되고 면접에서도 많이 물어보지만 프로그래밍을 할때도 종종 고려해야하는 요소이기도 합니다. 오늘은 이 주제에 대해 알아보고자 합니다.

기본 지식

본문에 앞서 읽으면 도움 될 만한 요소들을 준비했습니다.

  • 실행단위
    • cpu core 에서 실행하는 하나의 단위로 프로세스와 스레드를 포괄하는 개념

프로세서와 프로그램과 프로세스

프로세서

  • 프로세스가 동작될 수 있도록 하는 하드웨어 (=CPU)

프로그램

  • 하드 디스크에 저장된 코드 뭉텅이
  • 어떤 작업을 위해 운영체제 위에서 실행할 수 있는 파일(Ex. 웹 브라우저, 워드 프로세서, 카카오톡)

프로세스

  • 메모리에 올라간 프로그램
  • 운영체제 위에서 실행중인 프로그램 프로그램 명령어와 데이터들이 메모리에 올라오고 실행중 또는 실행 대기중인 상태
  • 프로그램에 Instance라고 생각하셔도 됩니다.

아래 그림은 프로그램이 프로세스로 로드 되는 과정을 보여줍니다.

쓰레드는 프로세스와 어떤 차이가 있는가
  • 프로그램이 프로세스가 될땐 크게 2가지 일이 일어납니다.
    1. 프로세스가 필요로 하는 재료들이 메모리에 올라간다.
      • 재료라고 해당되던 내용이 Code, Data, Heap, Stack 을 얘기합니다.
    2. 프로세스에 대한 정보를 담고 있는 PCB(Process Control Block) 블럭이 프로세스 생성시 함께 만들어집니다.
    • PCB에는 굉장히 많은 정보를 가지고 있습니다. 대표적으로 몇개를 보자면 아래와 같습니다.
      • process state : 현재 프로세스 상태
      • PID : 프로세스 고유 번호
      • Program Counter : 다음 명령어를 가리키는 역할
쓰레드는 프로세스와 어떤 차이가 있는가
  • 기본 지식에서도 설명했듯이 코어 한개는 한번에 한가지 일만 할 수 있습니다.(그림에서 보이는 CPU는 싱글코어라고 가정하겠습니다.)
  • 프로세스가 2개 있다고 가정할 때 (PCB_1 과 PCB_2 입니다.) PCB_1을 실행시키면 PCB_2 는 준비상태에 있어야 하고 다시 PCB_2를 CPU에 올리려고 하면 전환작업이 필요합니다. 이 전환작업이 Context switching라고 합니다.
  • 전환작업에는 프로세스가 필요하는 재료들이 다시 메모리에 올라가고 PCB의 정보들도 같이 다시 올라갑니다.
  • 하지만 이렇게 되면 전환 될 때마다 즉, Context Switching 이 일어날때마다 많은 과정이 뒤따릅니다.

이를 어떻게 해결할 수 있을까요? 여기서 등장하는게 경량화된 프로세스(lightweight process) Thread 라는 개념입니다. 쓰레드는 프로세스와 어떤 다른점이 있기 때문에 경량화된 프로세스라고 하는 것일 까요? 바로 쓰레드는 자기 자신의 자원을 다른 프로세스와 공유하지 않는 프로세스와 다르게 많은 부분을 공유합니다.

쓰레드는 프로세스와 어떤 차이가 있는가

스레드는 code, data, heap 자원을 공유하고 stack 자원만 공유하지 않습니다. 따라서 프로세스의 context switching 가 다르게 캐싱 적중률이 올라갑니다.(context switching 을 해줄때 자원을 많이 바꿀 필요가 없다는 의미입니다.)

Process vs Thread

본격적으로 프로세스와 스레드를 비교해보겠습니다.

  • 프로세스는 파일을 읽거나, HTTP 응답을 받거나, 네트워크를 통해 파일을 보낼때 등 여러 작업을 할 때 자식 프로세스를 만들거나 스레드를 만듭니다.
  • 스레드는 프로세스 안에 존재하고 메모리 관점에서 같은 메모리 주소를 공유하지만 자식 프로세스는 분리된 메모리 주소를 사용합니다.
    • 즉, 프로세스는 다른 프로세스와 독립적이게 작동합니다.
  • 프로세스는 다른 프로세스의 자원에 직접 접근 할 수 없습니다.
  • 자식 프로세스를 만들기 위해 fork()를 사용할 때 중복된 자원이 그대로 만들어지기 때문에 thread 를 생성하는것보다 더 비싼 작업입니다.

표로 만들어 비교하면 아래와 같습니다.

Process Thread

프로세스는 비교적 무거운 작업입니다. 스레드는 비교적 가벼운 작업입니다.
프로세스는 fork() 와 같은 함수를 사용하여 새로운 프로세스를 생성할 수 있습니다. 프로세스는 스레드를 pthread_create() 와 같은 함수를 사용하여 새로운 스레드를 생성할 수 있습니다.
각 프로세스는 자신만의 메모리 공간이 있고 다른 프로세스와 메모리를 공유하지 않습니다. 스레드는 같은 프로세스안에 있는 다른 스레드들과 메모리를 공유합니다. 같은 프로세스 안에 있는 스레드는 같은 주소 공간을 갖고 각자의 자료구조에 쉽게 접근할 수 있습니다.
프로세스끼리 통신을 하기 위해선 IPC를 사용하면 되지만 다른 메모리 주소 이기 때문에 느립니다. 같은 프로세스 안에 있는 스레드는 자원을 공유하기 때문에 스레드간의 통신은 IPC 보다 더 빠른 통신속도를 보여줍니다.
프로세스간의 Context switching 은 비싼 편입니다. 스레드간의 Context switching 은 상대적으로 덜 비싼 편입니다.

Process 와 Thread 각각 언제 사용해야 할까?

  • 무조건 이렇게 나눠질 수 있다는 아니지만 약간의 첨언을 드리자면 다음과 같습니다.
  • I/O 작업의 경우는 동시성(Concurrent) 를 사용하고 Thread 를 사용하는걸 권장합니다.
  • CPU 작업의 경우는 병렬성(Parallel) 을 사용하고 Process를 사용하는걸 권장합니다.

Multi-Processing vs Multi-Thread

Multi-Processing

  • 병렬성(Parallelism)을 기본으로 하는 프로그래밍입니다.
  • 싱글코어 CPU는 서로 다른작업에 대해서 CPU time 을 나눠써야 하지만 멀티코어 CPU나 분산된 클러스터는 서로 다른 작업에 대해서 한번에 다양한 일을 할 수 있습니다.

Multi-Thread

  • 동시성(Concurrency)을 기본으로 하는 프로그래밍입니다.(Concurrent programming 예시에 많이 등장합니다.)

그림으로 설명

쓰레드는 프로세스와 어떤 차이가 있는가
  • 왼쪽 그림은 Multi-process 를 나타내고 오른쪽 그림은 Multi-thread 를 나타냅니다.
  • 그림의 설명만 보면 Multi-threadMulti-process 에 비해 우수한거 같습니다. 그렇다면 Multi-thread 만 사용하면 될까요?
  • 그렇지 않습니다. 우선 Multi-thread는 서로의 자원을 공유하는 만큼 동기화 문제에 많은 신경을 써야합니다.
  • 또한 구글 크롬을 예시로 들어보자면 기존의 인터넷 익스플로어와 달리 크롬은 프로세스 기반을 사용하고 익스플로어는 쓰레드 기반을 사용합니다.
  • 크롬은 각 탭에 대하여 문제가 일어나도 전체 프로그램에 대해선 영향을 많이 미치지 않는것에 달리 인터넷 익스플로어는 아래와 같이 끔찍한 일이 벌어져 모든 탭이 다 닫혀야 하는 문제가 있었습니다.
  • 쓰레드는 프로세스와 어떤 차이가 있는가
  • 비록 크롬이 더 많은 리소스를 사용하는 방법일 수 있지만 각 탭에 대하여 독립적인 상태를 유지하므로써 더 사용자 경험이 좋게 만드는 방법을 제공해준다고 말할 수 있습니다.

결론

  • 이 글을 다 읽고 여러분이 대답할 수 있는 질문중 하나는 Process 와 Thread 는 same time에 동작할 수 있는가? 입니다.
  • 답은 경우에 따라 다르다 입니다.
    • 만약 CPU의 코어가 여러 개 가 있다면 코어의 갯수 만큼 ProcessThread 를 동시에(same time) 에 동작시킬 수 있습니다.
    • 하지만 싱글코어라면 서로 다른 ProcessThread 를 정확히 동시에 동작시킬 수 없습니다.
  • 이런 질문에는 이렇게 답변할 수 있습니다. 제가 싱글코어 CPU를 써봤는데 동시에 작동되는거 같던데요?
    • 실제로는 동시에(same time, Simultaneous) 에 동작하지 않습니다.
    • CPU가 CPU의 작동 시간을 나눌 수 있는 프로세스 스케줄링 알고리즘을 사용하여 동시에 작동하는것처럼 보일 뿐입니다.
  • 병렬성(실제로 동시에 실행되는것) 과 동시성(동시에 실행되는 것처럼 보이지만 실제론 프로세스들 끼리 교체되는것)은 동시에 일어나는가? 로 구별할 수 있습니다.
  • 모든 병렬 프로그래밍(Parallel Programming)은 동시성 (Concurrent)이지만 모든 동시성 프로그래밍(Concurrent Programming)은 병렬인것은 아닙니다.

더 알아볼것

  • Thread-safe 하게 도와주는 프로그래밍 도구
    • Closure
    • Lambda
    • Funcitonal Programming
    • Actor

참조

  • https://www.youtube.com/watch?v=1grtWKqTn50
  • https://www.youtube.com/watch?v=iks_Xb9DtTM
  • https://www.mineiros.io/blog/guide-to-multihreading-and-multiprocessing#concurrency