서브프로그램 수준 동시성

함수를 부르고도 끝나기를 기다리지 않는다면?

되짚기: 서브프로그램

부르면 멈추고, 끝나면 돌아옵니다

서브프로그램은 함수처럼 이름을 붙여 부르는 코드 묶음입니다. 부르면(호출) 부른 쪽은 멈춰서 기다리고, 서브프로그램이 끝나면 실행이 부른 쪽으로 돌아옵니다(반환).

굵은 선은 실행 중인 구간, 점선은 멈춰서 기다리는 구간입니다.

태스크

시작시킨 쪽이 멈추지 않습니다

다른 프로그램 단위와 동시에 실행될 수 있는 프로그램 단위를 태스크(task)라고 합니다. 태스크를 시작시킨 쪽은 기다리지 않고 자기 일을 이어 갑니다. 그래서 둘의 실행이 겹칩니다.

같은 것을 프로세스(process)나 스레드(thread)라고도 부릅니다. 세부는 다르지만 여기서는 같은 것으로 봅니다. 태스크 하나가 1편에서 본 제어 흐름 하나입니다.

서브프로그램과 다른 점

다른 점은 셋입니다

태스크는 직접 부르지 않아도 시작될 수 있고, 시작시킨 쪽을 멈추게 하지 않으며, 끝나도 실행이 시작시킨 쪽으로 돌아가지 않을 수 있습니다.

제어(control)는 지금 실행되고 있는 차례입니다. 1편의 제어 흐름에서 지금 실행 중인 자리를 가리킵니다. 직접 부르지 않았는데 시작되는 것을 암묵적으로 시작된다고 합니다.

두 종류

무거운 태스크, 가벼운 태스크

무거운 태스크(heavyweight task)는 자기만의 주소 공간에서 실행됩니다. 가벼운 태스크(lightweight task)는 여럿이 같은 주소 공간을 함께 씁니다. 그래서 가벼운 쪽이 더 효율적입니다.

주소 공간은 태스크가 쓸 수 있는 메모리의 범위입니다. 메모리는 값을 담는 칸이 줄지어 있는 곳입니다.

태스크 사이 통신

정보를 주고받는 길 셋

태스크는 대개 따로 놀지 않고 서로 맞물려 일합니다. 그러려면 정보를 주고받아야 합니다. 함께 쓰는 변수에 쓰고 읽거나, 호출하면서 값을 넘기거나, 메시지를 보냅니다.

비지역 변수는 그 단위 밖에 선언된 변수이고, 매개변수는 호출할 때 값을 넘겨받는 변수입니다. 다른 태스크와 전혀 통신하지 않는 태스크는 분리된 태스크라고 합니다.

스케줄러

프로세서를 누구에게 줄까

태스크가 프로세서보다 많으면 차례를 정해야 합니다. 이 일을 하는 프로그램이 스케줄러(scheduler)입니다. 실행할 준비가 된 태스크는 준비 큐에 줄을 서고, 스케줄러가 그 가운데 하나를 프로세서에 올립니다.

큐(queue)는 먼저 들어온 것이 먼저 나가는 줄입니다. 프로세서는 프로그램을 실제로 실행하는 장치입니다.

태스크의 상태

태스크는 다섯 상태를 오갑니다

새로 생긴 태스크는 준비 상태로 줄을 섭니다. 프로세서를 받으면 실행되고, 어떤 사건을 기다려야 하면 막힘 상태가 됩니다. 사건이 일어나면 다시 준비로 돌아갑니다.

준비는 프로세서만 받으면 바로 실행할 수 있고, 막힘은 기다리던 사건이 일어나야 실행할 수 있습니다. 영어로는 차례로 new, ready, running, blocked, dead입니다.

다음 편

태스크 둘이 같은 변수를 함께 쓰면 문제가 생깁니다

3편같은 변수를 둘이 동시에 고치면? 12강 목록