자 이번 글에서는 Thread와 Process가 뭔지, 둘의 차이는 무엇인지에 대해서 알아보도록 하자.
Program?
이를 위해서는 먼저 Program에 대해서 정의하고 가야 할 텐데, 나무위키에 따르면 Program이란
`어떤 문제를 해결하기 위하여 그 처리 방법과 순서를 기술하여 컴퓨터에 주어지는 일련의 명령문 집합체를 뜻한다.` 라고 한다.
우리가 PC에서 사용하는 게임, 메모장, 브라우저 등등이 모두 프로그램이다.
예를 들면 우리 머릿속에는 `밥먹기.` 라는 Program이 내장되어있다.
이 Program에는 `젓가락 들기`, `숟가락 들기`, `밥 뜨기`, `밥 입에 넣기` 등의 명령문들이 존재한다.
즉, 우리라는 사람 자체가 여러 가지 Program을 내장하고 있는 PC라고 할 수 도 있을 것이다.
Process?
그렇다면 Process는 무엇일까?
Process는 실행되고 있는 Program을 말한다.
즉, Program이 메모리상에 올라가 실제로 동작하고 있는 상태를 Process라고 말하는 것이다.
Process는 각각 독립적으로 동작하며, 시스템으로부터 자원(메모리 공간 등)을 할당받는다.
이 자원들은 어떠한 Process가 사용하고 있으면, 다른 Process에서는 사용할 수 없다.
위에서 말한 `밥먹기` Program을 다시 가져와서 이러한 Program은 우리의 머릿속에 저장되어 있다가
실제로 우리가 밥을 먹기 시작하면 `밥먹기` Program을 실행시켜서 작업을 수행한다.
이때 우리는 밥을 먹기 위해서 `밥먹기` Prgoram에 밥을 뜨기 위한 손, 먹기 위한 입 등의 자원을 할당한다.
PC에선 CPU, 메모리 영역(Code, Data, Stack, Heap 등)의 자원을 할당받아서 사용한다.
또한 우리 PC에서 Process는 수십 개가 넘어갈 수도 있는데 CPU는 하나면 어떻게 모든 Process가 동작할까?
실제로 CPU는 여러 프로세스들에 순서를 매겨서 고속으로 번갈아가면서 실행한다.
때문에 모든 Process들이 동시에 돌아간다고 느끼게 되고, CPU사양이 부족하면 렉도 걸리는 거다.
이러한 순서는 스케줄링(Scheduling)을 통해서 결정되는데, 자세한 설명은 이 글에서는 생략하도록 하겠다.
Thread?
그렇다면 Thread라는 건 무엇일까?
Thread는 한 Process내에서 동작하는 여러 실행의 흐름을 말한다.
즉, 우리가 코드를 작성하여 변수a를 만들고, 이 a를 printf로 출력하는 것이 실행의 흐름인데,
이러한 흐름을 Process가 할당받은 자원을 가지고 실제로 행하는 것이 Thread라고 할 수 있다.
기본적으로 하나의 Process에는 하나의 Thread가 존재하고, 모든 작업을 수행하는데 이를 Thread를 MainThread라고 한다.
하지만 실제로 우리가 사용하는 Program에서 하나의 Thread로만 동작하는 건 별로 없을 것이다.
Thread를 예로 들 때 일꾼이라는 말을 쓰기도 하는데, Process를 공장이라고 했을 때
한 공장에 한 명의 일꾼만 있으면 얼마나 일이 불편하겠는가?
두 개의 생산 라인이 있다고 했을 때, 첫 번째 라인에서 A를 만들고, 두 번째 라인에선 B를 만든다고 해보자.
하나의 Thread만 사용하는 경우 이때 첫 번째 라인에서 모든 A를 만들고, 이후에 B를 만들어야 한다.
즉, 이미 만들어져 있는 A가 활용되고 있지 않기 때문에 그만큼 시간이 낭비되는 것이다.
이를 Single Thread 방식이라고 하자.
Program에서도 마찬가지인데, 우리가 어떤 큰 Program에서 일정 시간이 지나면
사용자에게 알려주는 Timer를 추가한다고 생각해보자.
그러면 우린 시간이 지나는 걸 측정하는 작업을 수행해야 할 텐데, 만약 Single Thread방식이라면
우리는 이 Timer가 다 끝나고, 알림이 올 때까지 까지 다른 어떤 작업도 못하고 기다리고 있어야 한다.
너무나도 비효율적이지 않은가?
그래서 이러한 문제를 해결하기 위해서 등장한 것이 MultiThread, 비동기 처리이다.
비동기 처리는 Program이 어떠한 작업을 수행할 때 이 작업을 기다리지 않아도 된다.
즉, 작업 A와 작업 B를 동시에 수행할 수 있는 것이다.
그리고 이를 가능하게 해주는 것이 바로 MultiThread라는 것이다.
다시 공장 이야기로 돌아가 보자.
이제 이 공장에는 두 명의 일꾼이 생겼고, 이를 관리/감독하는 관리자도 생겼다.
이러한 형태를 MultiThread라고 하며, 여기서 관리자를 MainThread, 두 명의 일꾼을 WorkerThread라고 해보자.
MainThread, 관리자는 이 공장이라는 Process의 큰 흐름을 진행시키는 역할을 한다.
즉, 주문을 받아서 생산라인을 가동시키고 완성품을 만들어서 출고하는 일련의 과정들을 관리자가 진행시킨다.
그리고 이 과정에서 각각의 작업들을 WorkerThread에게 진행시키라고 던져주는 것이다.
그럼 이제 WorkerThread이야기로 들어가 보자.
기존의 Single Thread방식에선 A를 모두 만들고 나서야 B를 만들 수 있었다.
그런데 MultiThread에선 A가 하나 완성되면 이를 사용해 바로 B를 만들 수 있는 것이다.
이로써 우리는 쓸데없는 시간낭비를 줄이고 최적의 효율로 작업을 진행시킬 수 있게 되었다.
위 그림에선 두 Thread가 동시에 작업한는 것 처럼 그려놧는데, 실제로는 Process들처럼
두 Thread가 고속으로 번갈아가면서 작업을 수행한다.
Thread들은 Process가 System으로부터 할당받은 자원들을 일부 공유하게 되는데,
위에서 Process는 Code, Data, Heap, Stack등의 메모리 영역을 할당받는다고 이야기했다.
여기서 Thread는 Code, Data, Heap은 공유하고, Stack공간은 각각 나눠서 독립적으로 가지게 된다.
이러한 자원 공유 때문에 MultiThread사용 시 반드시 주의해야 할 점이 `동기화`이다.
다음과 같은 예제를 본 적이 있을지 모르겠는데, Process P에 어떠한 변수 A와 WorkerThread T1, T2, T3가 있다고 해보자.
그리고 각 Thread가 변수 A에 T1은 1, T2는 2, T3는 3이라는 값을 입력한다고 해보자.
자, 모든 Thread동작이 끝났을 때 과연 A의 값은 어떻게 돼있을까?
T1, T2, T3니까 마지막에 있는 T3의 3? 아니면 맨 앞에 있는 T1의 1? 이도 저도 아닌 T2의 2?
정답은 `모른다`이다.
실제로 MultiThread동작에서 우리는 Thread가 어떠한 순서로 실행되는지 그 순서를 알 수 없다.
그래서 위와 같이 변수 A에 마구잡이로 여러 Thread가 값을 입력하면 그 결과를 알 수가 없는 것이다.
왜냐하면 Thread는 자원을 `공유`하기 때문에 변수 A라는 공유된 자원에 자신에게 주어진 동작을 수행할 뿐이기 때문이다.
위에서 Process가 CPU를 할당받을 때 어떤 순서로 할당받을지는 Scheduling을 통해서 System이 정해준다고 이야기했다.
하지만, Thread는 이 Scheduling을 프로그래머가 직접 적절하게 구현해주어야 한다.
안 그러면 우린 우리가 만든 Program이 어떻게 돌아가는지도 제대로 모르게 될 테니까.
그래서 MultiThread동작에서 매우 중요한 것이 `동기화`라는 것이다.
Process와 Thread의 차이점
그리고 이때 Process와 Thread의 차이가 극명하게 드러나게 되는데,
위에서 말했듯이 Process는 System으로부터 자원을 할당받아 `독립`적으로 동작하고
Thread는 Process가 System으로부터 할당받은 자원을 `공유`한다.
여기서 다시 공장 이야기로 돌아가 보자.
Process는 각각 하나의 `독립`된 공장이라고 할 수 있는데, A와 B공장이 있다고 해보자.
B공장이 어떠한 이유로 망해서 가동을 안 한다고 했을 때 이것이 A공장과 관계가 있을까?
물론 없다.
왜? A와 B는 각각 `독립`적으로 가동하고 있으니까.
그렇다면 이번에는 공장 안으로 들어가 보자.
위에서 말한 생산라인을 생각해보면, B를 만들려면 다른 생산라인에서 A를 받아서 작업을 수행해야 한다.
즉, 여기선 Thread들이 자원을 `공유`한다는 것이다.
그런데 만약 A를 만드는 생산라인이 고장 나서 기능을 못하게 된다면 어떻게 될까?
일단, A를 받아서 사용하는 B를 만드는 생산라인이 기능을 못하게 될 것이다.
그러면 이렇게 제품을 만드는 생산라인이 기능을 하지 않기 때문에 제품을 출고할 수가 없다.
이는 공장의 기능 정지가 되고, Process가 동작을 끝까지 수행할 수 없게 된다는 뜻이다.
이러한 부분이 Program->Process->Thread의 관계에서 Process와 Thread의 큰 차이점이라고 할 수 있다.
이번 글은 이 정도로 마치도록 하겠습니다.
위에서 말했듯이 Process는 각각 독립적으로 동작하기 때문에
Process간 통신은 번거롭고 까다로운 작업이고, 반면 Thread는 다른 Thread와 정보 공유가 쉽다는 장점도 있습니다.
글이 도움이 되셨으면 좋겠습니다.
'Computer Science' 카테고리의 다른 글
큐(QUEUE)와 스택(STACK) (0) | 2021.12.11 |
---|---|
배열(Array)과 리스트(List) (0) | 2021.06.07 |
REST API란? (0) | 2021.01.25 |
URL과 URI의 차이 (0) | 2021.01.05 |
하드 링크와 심볼릭 링크 (0) | 2020.11.07 |