프로세스와 스레드
작성일
들어가기 전에
키워드
-
실행 단위: cpu core에서 실행하는 하나의 단위로 프로세스와 스레드를 포괄하는 개념
→ 실행단위는 프로세스와 스레드 모두를 포괄한 개념이다. 따라서, 실행단위라고 했을 때 프로세스일 수도 있고 스레드일 수도 있다.
-
(부연 설명이 없는) 프로세스: 하나의 스레드만 가지고 있는 단일 스레드 프로세스
→ 프로세스와 스레드가 완전히 다른 무언가가 아니다.
-
동시성: 한 순간에 여러가지 일이 아니라, 짧은 전환으로 여러가지 일을 동시에 처리하는 것처럼 보이는 것이다.
프로그램과 프로세스
- 프로그램:
코드 파일
, 프로그램: 실행시키기 전에는 코드가 구현되어 있는 파일일 뿐이다. - 프로세스: 프로그램이 실행 되어서 사용할 수 있는 무언가가 되는데 그게
프로세스
이다.
미리 알면 좋은 Process 지식
프로그램이 프로세스가 되면서 2가지 일이 일어난다.
일단 프로세스가 필요로 하는 재료들이 메모리에 올라간다. 메모리 영역은 4가지 영역(Code, Data, Heap, Stack)이 있다.
- Code: 실행 명령을 포함하는 코드들
- Data: Static 변수 혹은 Global 변수
- Head: 동적 메모리 영역
- Stack: 지역변수, 매개변수, 반환 값 등등 일시적인 데이터
두번째로 해당 프로세스에 대한 정보를 담고 있는 PCB(Process Control Block) 블럭이 프로세스 생성 시 만들어진다.
- Pointer: 프로세스 상태 중에 준비 상태나 대시 상태의 큐를 구현하기 위한 포인터
- Process State: 현재 프로세스 상태를 담는다.
- Process Number(ID): 고유 번호를 담는 PID
- Program Counter: 다음 명령어를 가리키는 프로그램 카운터
등등이 있다.
Process & Thread
프로세스
개발자는 코딩을 하기 전에 유튜브에서 ‘이노래 뭐지’ 팝송 플레이리스트를 튼다. 그 후 코딩을 하기 위해 Intellij를 연다. 중요한 알람이 올 수 있으므로 slack을 켠다. 그리고 개발 필수템인 크롬을 킨다. 이렇게 대부분의 사람들은 하나의 프로세스를 사용하기 보다 여러가지를 동시에 사용한다.
하지만 원래 하나의 프로세스
가 실행되기 위해서 CPU를 점유하고 있으면 다른 프로세스는 실행 상태에 있을 수 없다. 노래를 듣다가 코딩을 하기 위해 Intellij를 키면 노래가 꺼지게 된다. 즉, 여러 프로세스가 동시에 실행되고 관리되는 것처럼 보이지만 실제론 여러개의 프로세스를 시분할
, 즉 짧은 텀을 반복하면서 전환해서 실행 시키는 것이다.
동시에 실행시키고 싶은 프로세스 A와 B가 있다고 가정하자. A를 실행시키기 위해 실행 상태로 전환하고 CPU에 적재된다. B는 준비상태에 있다. 이제 B를 실행시키기 위해서는 A를 먼저 준비상태로 전환하고 B가 CPU에 적재 되어야 한다. 이 과정을 반복하게 될때 발생하는 것이 컨텍스트 스위칭
이다.
컨텍스트 스위칭은 매우 번거로운 작업이다. 이 부분을 개선하기 위해 등장한 것이 경량화된 프로세스 버전인 스레드
이다.
참고 컨텍스트 스위칭 컨텍스트 스위칭이란 CPU에서 여러 프로세스를 돌아가면서 작업을 처리하는 과정을 말한다.
스레드
스레드
를 경량화된 프로세스라고 부르는 이유는 하나의 프로세스 안에 다수의 스레드가 있을 때 공유되는 자원이 있기 때문이다. 프로세스의 메모리 구조 중 Stack을 제외한 나머지 Code, Data, Heap을 모두 공유한다. 공유되는 자원이 있기 때문에 이전 처럼 컨텍스트 스위칭이 일어날 때 캐싱 적중률이 올라간다.
프로세스와 스레드 예
예를 들어 공용 회의실이 있고 그 안에는 티비, 스피커, 리모컨이 있다고 가정하자. A팀이 먼저 회의실을 예약하여 사용했다. 이때 프로세스라면 A팀이 회의를 마치고 티비, 스피커, 리모컨을 가지고 나간다. 그 다음 팀인 B팀이 회의실을 사용하려면 티비, 스피커, 리모컨을 가지고 와야 회의실을 이용할 수 있다. 그러나, 스레드를 사용하면 공용자원인 티비, 스피커, 리모컨은 그대로 두고 자신들의 개인 노트북만 가지고 와서 연결하여 사용하면 된다.
Multi-process vs Multi-thread
멀티 프로세스와 멀티 스레드는 두가지 개념이 모두 처리 방식의 일종이다. 한 어플리케이션에 대한 처리 방식이라고 생각하면 편하다.
한 어플리케이션이 여러가지 일을 처리할 때가 있다. 예를 들어 여러 사용자가 로그인을 요청하는 상황이 있다고 가정한다. 한 프로세스는 매번 하나의 로그인을 처리하기 때문에 동시에 처리할 수가 없다. 그래서 부모 프로세스가 fork()
해서 자식 프로세스를 만들어서 일을 처리한다. 이때 자식 프로세스는 부모와 별개의 메모리 영역을 확보하게 된다.
반면, 스레드는 한 프로세스 내에서 구분이 지어진 실행 단위이다. 한 어플리케이션에 대한 작업의 단위가 나눠질 때가 많다. (Intellij를 사용하는데 테스트도 실행하면서 동시에 코드를 수정하는 경우) 이때 각각의 스레드가 그 작업들을 담당한다.
차이점
멀티 프로세스는 각 프로세스에 독립적이므로 IPC를 사용해 통신해야 한다. 자원 소모적이며 개별 메모리 차지한다. 따라서, 컨텍스트 스위칭 비용이 크다. 하지만 독립적으로 존재하기 때문에 동기화 작업이 필요없다.
반면, 멀티 스레드는 스레드끼리 긴밀하게 연결되어 있다. 따라서, 공유된 자원으로 통신 비용이 절감되고 메모리를 효율적으로 사용할 수 있어 컨텍스트 스위칭 비용이 적다. 단, 공유 자원 관리를 해야한다. (동기화 작업)
이렇게 보면 멀티 프로세스보다 멀티 스레드가 훨씬 좋아보이는데 왜 멀티 프로세스를 이용할까?
그 이유에 대한 예시는 크롬과 IE를 얘기할 수 있다.
크롬은 멀티 프로세스 사용, IE는 멀티 스레드 사용한다.
IE를 사용하면서 다수의 탭을 사용하고 있다가 경고 메시지가 나오며 창 전체가 꺼지는 경험을 한적이 있을 것이다. 멀티 스레드를 이용했기 때문에 발생하는 문제이다. 긴밀하게 연결되어 있기 때문에 한 스레드(1개의 탭)에 문제가 생기면 전체 프로세스에 영향이 있다. 반면, 구글 크롬은 다소 비효율적인 부분이 있을 수 있지만 멀티 프로세스를 사용하기 때문에 멀티탭 간에 영향을 덜 받는다.
Multi-core
멀티 프로세스와 멀티 스레드는 처리방식의 일종이기 때문에 소프트웨어 분야에 가깝고 멀티 코어는 하드웨어 측면에 가깝다. 멀티 코어와 관련된 키워드는 동시성과 병렬처리이다.
동시성
이란 하나의 코어에서 하나 이상의 프로세스(혹은 스레드)가 번갈아가면서 진행되지만 동시에 진행되는 것처럼 보이는 것이다. (동시성은 짧은 순간에 CPU의 시간을 분할해서 동시에 하는 것처럼 보이게 한다.)
하지만 멀티코어는 병렬처리
즉, 물리적으로 여러 코어를 사용해서 다수의 실행 단위를 한 순간에 동시에 처리할 수 있게 해준다. (병렬처리란 둘 이상의 코어에서 동시에 하나 이상의 프로세스(혹은 스레드)가 한꺼번에 진행되는 것)
참고 리눅스에서 프로세스와 스레드
리눅스 커널
에서는 프로세스와 스레드를 동일하게 본다.스레드는 사용자 스레드와 커널 스레드로 나뉜다. 이름에서 알 수 있듯이 각 스레드를 담당하는 레벨이 하나는 사용자 레벨이고 하나는 커널 레벨이다. 사용자 스레드와 커널 스레드는 어떠한 연관관계가 있다.
리눅스는 일대일 모델이다. 하나의 사용자 스레드당 커널 스레드 하나가 매칭된다. 그래서 리눅스 커널 입장에서 보면 ‘각각의 스레드가 하나의 프로세스다’ 라고 표현한다. 그런데 여기서의 프로세스는 이전에 설명했던 프로세스가 각각 다른 메모리를 가진 것과는 다르게 메모리를 공유한다. 그래서 이것들을
light weight process
라고 구분해서 부른다. 이전에 설명했던 프로세스는 프로세스 고유번호(PID)를 가지고 있다. 그렇다면 리눅스는 스레드가 각각 다른 PID를 가지고 있을까? 그건 아니다. 확인해보면 한 프로세스의 생성된 스레드는 모두 같은 PID를 가지고 있다.더 자세히 보면 TGID라는 스레드 그룹 아이디를 가지고 있고 TID라는 스레드 아이디도 있다. 그래서 사용자 레벨입장에서 보면 스레드 그룹 아이디가 PID로 보여지고 커널 입장에서 보면 TID가 PID로 인식이 된다. 그래서 관점을 다르게 해서 이해 해야 한다. 그래서 커널 입장에서는 각각이 다른 프로세스로 보이게 된다.
[참조] 이 글은 해당 영상(링크)을 참고하여 작성한 글입니다.