우리는 흔히 프로그램을 실행하면 프로그램의 프로세스가 생성되고 CPU 가 이를 실행한다고 알고 있다. 그렇다면 프로세스는 정확히 무엇이고 프로세스와 함께 거론되는 스레드는 무엇일까?
간단하게 프로세스는 실행되는 프로그램의 수행 단위이고 스레드는 CPU 에서 실행되는 프로세스의 실행 단위이다.
먼저 사용자가 프로그램을 실행하면 프로세스가 생성되어 각종 자원을 할당 받은 후 CPU 에게 실행되기를 기다리는데 이때 수행되기 위한 프로세스의 정보의 집합은 문맥(Context)라고 한다.
문맥에는 프로세스가 실행되기 위한 CPU 정보, 메모리 정보, OS 자원 정보 이며 이는 각각 다음과 같다.

즉, CPU 는 프로세스의 문맥을 알아야 실행할 수 있으며 실행 중이던 프로세스를 해제하고 다른 프로세스를 실행할 때 문맥에 실행되었던 정보를 저장해두며 향후 다시 CPU 에 할당되었을 때 이전에 실행되던 정보 이후로 이어서 진행이 가능하며 이러한 프로세스의 문맥 정보를 바꾸는 것을 문맥 교환 (Context Switch) 라고 한다.
여기서 PCB 는 하나의 생성된 프로세스에 대한 정보를 담은 객체로 실행되기 기다리는 OS 의 각종 프로세스 Queue 에는 실제 프로세스가 담기는게 아닌 이 PCB 가 연결리스트 형식으로 아래와 같이 담겨있다.

결과적으로 프로그램은 실행되기 위해 자신의 프로세스를 생성하며 생성된 프로세스들은 CPU 에게 수행되기 전까지 PCB 정보 단위로 OS 의 커널의 프로세스 Queue 에서 대기하며 자신의 차례가 되면 실행되며 각종 Interrupt(입출력 신호나 System Call 혹은 외부 이벤트) 혹은 OS 의 CPU 스케쥴링 정책에 따라 문맥 교환을 하게 된다.
그래서 프로세스는 다음과 같은 그림으로 상태가 변화하며 수행된다.

프로세스는 생성된 직후 Ready 상태로 Job Queue 에 들어가 CPU 를 할당 받기 전까지 대기한다. 이때 OS 는 보다 모든 프로세스에게 공평하게 그리고 효율적으로 자원을 분배 하기 위해 프로세스 혹은 CPU 스케쥴링을 통해 프로세스 간 문맥 교환을 진행한다. CPU 를 반납한 프로세스는 다시 Job Queue 로 돌아가거나 혹은 Blocked 상태가 되어 다시 CPU 를 할당 받길 기다리며 최종적으로 작업을 마치고 종료되기 전까지 위의 순환을 반복한다.
이때 Ready 는 즉시 실행이 가능한 상태로 언제든 CPU 를 할당 받으도 실행 가능하지만 Blocked 상태에서는 I/O 데이터가 필요하는 등 CPU 를 할당 받아도 실행 불가능한 상태로 반드시 Ready 상태를 거쳐 실행되어야한다.
이후 프로세스가 CPU 에게 수행되기 시작하면 그때부터는 프로세스의 실행 단위인 스레드의 영역으로 들어가게 된다.
먼저 스레드를 알기 앞서 프로세스는 생성 시 OS 에게 실행 되기 위한 자신의 정보를 담기 위해 다음과 같은 주소 공간을 메모리에 할당 받는다.

실제 영역은 더 세분화 되어있지만 프로세스의 주소 공간은 크게 위와 같이 4개의 영역으로 나뉘어져 있으며 코드가 실행됨에 따라 Stack/Heap 영역의 크기가 동적으로 변한다.
이때 프로세스의 코드가 실행되는 하나의 흐름을 스레드라고 하며 우리가 디버그 모드로 진행할 경우 보이는 디버그 진행 라인과 비슷한 개념이다.

이때 실행된 스레드는 프로세스 내부의 자원을 가지고 코드를 실행하며 프로그램의 코드 실행하는 현재 정보를 담고 있는 Stack 과 Register 만을 독립적으로 할당 받고 나머지는 프로세스의 다른 영역의 정보를 그대로 가져다 쓴다.

프로세스의 스레드의 독립된 고유 정보는 프로세스의 PCB 와 마찬가지로 Thread Control Block 인 TCB 로 관리되며 TID, PCB Pointer(어떤 PCB 의 Thread 인지), Next TCB Pointer, 상태, 레지스터 같은 정보들을 가지고 있다.
여기서 문제는 하나의 프로세스가 실행되는데 하나의 스레드만 실행되는 것이 아니라는 것이다. 예를 들어 커다란 식당에서 가지각색의 요리를 주문 받아 만든다고 가정해보자. 요리를 만들기 위해선 특정 공간만큼의 주방이 있어야하고 주방에 식기와 재료들이 갖춰져야 한다. 이때 A라는 음식의 요청이 들어왔고 A 라는 요리를 만드는 도중에 다시 A 요리 요청이 들어오면 A 를 만들기 위한 똑같은 주방에 식기와 재료를 갖춰야 할까? 아니다 그냥 기존의 주방에서 똑같은 과정으로 요리를 진행하면 다시 주방을 준비하는 시간을 줄일 수 있으며 이러한 동작 방식을 멀티 스레드라고 한다.
하지만 멀티 스레드는 큰 문제가 하나 있는데 그것은 잘못 설계된 코드에 따라 위 공유 영역(Critical Section = 임계 영역)의 정보를 서로 침해할 수 있다는 것이다. 그렇게 되면 데이터의 정합성이 깨지게 되고 프로그램을 실행하는데 오류가 발생하게 되며 이를 피하기 위해 프로세스 동기화라는 기법을 사용해 정합성을 맞추기도 하며 아예 여러 프로세스를 동시에 실행하는 멀티 프로세스로 설계하기도 한다.

그래서 프로그램 설계 시 반드시 임계 영역의 부작용 고려하여 설계해야하고 다음으로 프로세스와 스레드 설명 간 나왔던 스케쥴링, 프로세스 동기화에 대해 더 알아보려고 한다.