비유: 웨이터가 있는 식당
식당에 웨이터 한 명(= CPU)이 있고, 여러 손님(= 작업, 스레드)이 있다고 가정해보겠습니다.
단일 작업 처리 (동시성 X)
웨이터가 한 손님의 주문을 받고, 음식 나오기를 기다리고, 그 손님에게 음식 가져다주고, 계산까지 다 끝낸 후에야 다음 손님에게 갑니다.
-> 한 번에 한 사람만 처리 = 병목 발생
동시성 (Concurrency)
이번엔 웨이터가 좀 똑똑합니다.
손님 1의 주문을 받고
주방에 주문을 넣고 기다리는 동안
손님 2의 주문을 받고
그 사이에 주방에서 손님 1의 음식이 나왔으면 가져다주고
또 손님 3의 주문도 받고...
이렇게 계속 "기다리는 시간"을 낭비하지 않고 다른 손님의 일을 처리합니다.
-> 실제로 동시에 여러 손님을 처리하는 건 아니지만,
짧은 시간에 여러 손님의 요청을 번갈아 처리하면서 마치 동시에 처리하는 것처럼 보입니다.
이게 바로 동시성입니다
단일 코어(=웨이터 1명)가 여러 작업(=손님)을 효율적으로 처리하려면 시간을 쪼개고 문맥을 바꾸며 번갈아 일하는 방식으로 작동합니다.
이런 방식이 동시성입니다. 실제로는 한 번에 한 작업만 하지만, 빠르게 전환하며 처리하니 동시에 돌아가는 것처럼 보이는 것이죠.
주의할 점
손님 1과 손님 2가 동시에 계산하려고 하면 문제가 생길 수 있습니다 (= Race Condition)
웨이터가 어떤 손님의 요청만 계속 처리하고 나머지는 무시하면 문제가 됩니다 (= Starvation)
두 손님이 서로 음식을 주고받으려다 멈추는 경우도 있습니다 (= Deadlock)