프로세스(process)와 스레드(thread)의 관계는 개념적으로 크게 두 가지 세계관이 존재한다
세계관 1
임의의 프로그램(program)이 실행되려면 기본적으로 가지고 있어야 하는 리소스들(메모리 공간, 프로그램 코드, 환경 변수, 프로세스 ID)이 있다
프로그램이 실행되면 OS가 이런 리소스들을 부여하고, 메모리에 올려서 실행 가능한 형태로 만드는데
이렇게 리소스를 부여받아 실행 중인 (혹은 실행 가능한) 프로그램을 프로세스라고 부른다
하지만 실제로 CPU에서 (요즘은 멀티코어니까 각 코어에서) 실행(execution)되고 스케줄링(scheduling) 되는 것은 스레드다
그렇기 때문에 프로세스는 최소 하나의 스레드를 반드시 가져야 하며,
그러므로 이 세계관에서는 스레드 또한 프로세스가 가지는 리소스의 한 종류로 보게 된다
프로그램이 실행되면 기본적으로 프로세스와 그 프로세스에 속한 스레드 하나가 생성된다. (== 싱글-스레드 프로세스)
이때 최초의 스레드를 메인 스레드(혹은 primary 스레드)라고 부르기도 한다
그리고 이 메인 스레드에서 추가로 스레드들을 만들게 되면
이 프로세스는 여러 개의 스레드들을 가지게 되고 (== 멀티-스레드 프로세스)
이 프로세스의 가상 메모리 주소 공간과 그 외 여러 리소스들을 자신에게 속한 여러 스레드들과 공유해서 사용하게 된다
즉, 이 세계관에서는 프로세스와 스레드의 관계는,
프로세스는 스레드들을 들고 있는 컨테이너(container)인 것이다
그리고 보통 우리는 이 세계관으로 프로세스와 스레드 관계를 이해를 하고 있다
세계관 2
(리눅스가 이 방식이다. 혹시 리눅스 커널 전문가가 계시면 이게 정확한지 피드백 부탁드립니다)
리눅스는 엄밀히 말하면 프로세스와 스레드 개념이 없고 태스크(task)라는 개념이 있을 뿐이다
새로운 리소스를 할당 받는 것도 태스크고, CPU 코어에서 실행되고 스케줄링 되는 것도 태스크다
즉, 태스크는 (세계관 1의 관점에서는) 상황에 따라 프로세스처럼 보일 때도 있고 스레드처럼 보일 때도 있다
예를 들어 보자
리눅스에서 프로그램을 실행하게 되면 새로운 리소스(가상 메모리 주소 공간 등등)를 할당받은 태스크가 하나 만들어진다
이 태스크를 A라고 하겠다
그러면 세계관 1의 관점으로 태스크 A를 해석해 보면, 태스크 A는 프로세스 혹은 싱글-스레드 프로세스 혹은 스케줄링의 단위가 된다는 시각에서 스레드라고 볼 수도 있겠다
하지만 어쨌든 실제로는 태스크 하나가 있을 뿐이다
그런데 여기서 새로운 태스크 B를 만들었다고 하자
이때 태스크 B가 새로운 가상 메모리 주소 공간을 가지도록 만들어진 것이 아니라
이미 존재하던 태스크 A의 가상 메모리 주소 공간을 공유하도록 (즉, 태스크 A의 리소스를 공유하도록) 만들어졌다면,
그렇다면 세계관 1의 관점으로 보면 태스크 A와 태스크 B를 합쳐서 프로세스 혹은 멀티-스레드 프로세스라고 볼 수 있고
태스크 A와 태스크 B 각각은 스레드라고 볼 수 있다
개인적으로는 1번으로 이해하는 것이 더 좋다고 생각하는데
이미 우리가 1번 방식으로 많이 이해하고 있기도 하고
1번 방식은 2번 방식을 개념적으로 커버할 수 있기 때문이다
쉬운코드는 본질에 충실합니다
👉 프로세스, 스레드, 멀티프로그래밍, 멀티태스킹, 멀티스레딩, 멀티프로세싱 개념이 궁금하다면 영상 보러 가기