개발을 하다보면 계산을 병렬적으로 처리할 필요가 있습니다. 그때 우린 흔히들 멀티쓰레드를 사용해라 라고 합니다.
멀티쓰레드는 쓰레드를 여러개(멀티)로 사용한다는건데, 그럼 과연 쓰레드는 무엇일까 알아봅시다.
쓰레드(Thread) 정의
실행 중인 프로세스(≒프로그램) 내에서 실제로 작업을 실행하는 주체를 의미합니다.
아래 코드를 실행시키는 것도 하나의 쓰레드가 실행한다고 보면 됩니다.
실행 결과는 당연히 아래와 같습니다.
그러면 하나의 쓰레드 라는것은 여러개가 존재 가능하다는 것입니다.
단순하게 쓰레드를 2개 추가 실행시키는 예제 코드와 결과는 아래와 같습니다.
쓰레드를 2개를 추가로 실행시켜 각 쓰레드마다 hello()라는 함수를 실행시키는 간단한 예시 코드입니다.
실행 결과는 아래와 같습니다.
이번엔 Hello World!가 두번 나오는것을 확인 할 수 있습니다.
이 결과로 보아 쓰레드 1개당 주어진 일을 별개로 실행 한다는것을 확인 할 수 있습니다.
쓰레드 구조
쓰레드의 구조는 아래 그림과 같습니다.
쓰레드는 현 프로그램(프로세스)의 코드, 데이터, 파일들을 공유하고 레지스터, 스택을 고유의 영역으로 할당 받습니다.
여기서 말한 코드, 데이터, 스택은 메모리 영역을 의미합니다.
메모리 관련 정보를 원하시면 아래 링크를 통해 제가 올린 글을 보시면 됩니다.
그럼 레지스터는 무엇이기에 따로 할당이 되는지 궁금할 수 도 있습니다.
여기서 레지스터는 PC 레지스터입니다.
PC 레지스터는 다음에 실행할 명령어 주소를 가지고 있습니다.
명령어 주소는 왜 필요할까? 아래 예제 코드를 보겠습니다.
a라는 int 형 변수에 10으로 초기화.
변수 a에 5를 더하기.
변수 a의 값을 출력.
이렇게 3개의 명령어가 존재합니다.
컴퓨터는 명령어를 실행하기 위해서는 각 명령어가 담긴 위치를 알아야만 합니다.
만약 첫번째 코드(명령어)만 저장된 위치를 알고 다른 코드가 저장된 위치를 모른다면
int a = 10; 을 실행 이후 다음 코드를 불러와서 CPU에서 실행을 해야하지만,
a += 5; 라는 코드가 어디에 위치해 있는지 알수 없어서 코드를 불러오지 못해 에러가 발생할 것입니다.
여기까지는 이해가 되실겁니다. 하지만 이런 의문이 들 수도 있습니다.
"그런데 왜 굳이 이걸 분리해서 각 쓰레드마다 할당을 해야하지? 자원 낭비 아닌가?"
이는 쓰레드가 두개 이상일 경우 필요합니다.
예제 코드와 설명으로 설명드리겠습니다.
참고로 예시로 드리는 설명은 레지스터의 필요성과 목적에 대한 설명이기에,
그 외 부분은 이해하기 쉽도록 한 예시(ex: 메모리 주소)이므로 이해 부탁드립니다.
코드 자체는 단순합니다. 기존 코드와 같은 역할을 하는 calc()와 5를 빼는 cale2()이란 함수가 존재합니다.
그리고 이 함수들을 실행하는 두개의 쓰레드가 존재합니다.
프로그램이 실행이 되면 대략 이런 구조로 되어 있습니다.
thread1의 레지스터는 1번 메모리 주소를 가르키고 있고, thread2의 레지스터는 4번 메모리 주소를 가르키고 있습니다.
여기서 CPU가 thread1을 실행하려면 1번 메모리에 가서 실행시킬 코드를 불러와 실행합니다.
이후 구조는 이렇게 변경이 될것입니다.
만약 2번 메모리에 있는 코드를 실행하기 앞서 thread2나 다른 급한 일로 CPU가 실행을 못하고 다른 일을 하다가 올 경우,
다시 thread1의 레지스터를 참고해 2번 메모리에 있는 코드를 불러와 실행하면 됩니다.
이렇게 여러 일을 쓰레드마다 각자 실행하기 위해 레지스터가 각자 할당이 됩니다.
코드를 실행하면 결과는 아래처럼 나옵니다.
스택을 개별 할당하는 이유도 레지스터를 각자 할당하는 이유와 동일합니다.
이렇게 스택도 쓰레드별 각자 할당하였기에 서로의 데이터가 별도로 보장이 됩니다.
다음 포스팅에서 멀티 쓰레드에 대해 좀 더 자세히 알아보겠습니다.
'개발잡담 > 공부' 카테고리의 다른 글
멀티쓰레드는 쓰레드랑 어떤게 다를까 (0) | 2023.09.13 |
---|---|
힙? 스택? 메모리란 무엇일까 (0) | 2023.09.07 |
Buffer란 무엇일까? (0) | 2023.09.06 |
DB에서 transaction이란 뭘까 (0) | 2023.08.10 |