Context Switching Blocking Non-blocking
3줄 요약
- Blocking은 작업이 끝날 때까지 현재 thread가 다음 일을 하지 못하고 기다리는 실행 방식이다.
- Non-blocking과 async는 thread 점유를 줄일 수 있지만 코드 복잡도와 backpressure 설계가 필요하다.
- 실전 판단은 기술 유행이 아니라 병목이 CPU인지, I/O인지, thread pool인지에 따라 달라진다.
핵심 정리
- Blocking I/O는 이해하기 쉽지만 동시 요청이 많으면 thread를 오래 점유한다.
- Non-blocking I/O는 적은 thread로 많은 연결을 다룰 수 있지만 event loop를 막으면 전체 지연이 커진다.
- Java NIO와 Servlet async, WebFlux, Netty는 처리 모델이 다르므로 같은 API라도 병목 위치가 달라진다.
- Thread pool starvation은 task가 pool thread를 잡은 채 같은 pool의 다른 task를 기다릴 때 자주 발생한다.
- Blocking과 non-blocking 선택은 트래픽, 외부 I/O 시간, 팀 운영 능력, 관찰 도구를 함께 보고 결정한다.
헷갈리는 지점
- Async를 쓰면 항상 빨라진다고 오해하기 쉽다.
- Async는 대기를 다른 방식으로 배치할 뿐 외부 시스템 응답 시간을 없애지 않는다.
- Queue와 backpressure가 없으면 장애 전파가 더 커질 수 있다.
- Non-blocking은 thread가 필요 없다는 뜻으로 보기 쉽다.
- Event loop도 thread에서 실행되고 CPU 작업은 결국 core를 사용한다.
- 중요한 것은 대기 중인 연결이 worker thread를 오래 점유하지 않는다는 점이다.
- Blocking은 나쁜 방식이라고 단정하기 쉽다.
- 낮은 동시성과 단순한 운영에서는 blocking 모델이 더 명확하고 안전할 수 있다.
- 문제는 blocking 자체보다 thread와 timeout, pool을 설계하지 않는 것이다.
확인 질문
- Blocking이 thread를 점유한다는 뜻은 무엇인가?
- 외부 I/O나 lock이 끝날 때까지 해당 thread가 다른 요청을 처리하지 못한다는 뜻이다.
- Non-blocking 모델에서 가장 조심할 것은 무엇인가?
- Event loop를 CPU 작업이나 blocking 호출로 막아 전체 연결 처리를 지연시키는 것이다.
- Thread pool starvation은 왜 생기는가?
- 제한된 pool thread가 모두 대기 작업에 묶여 새 작업이나 완료 작업을 실행할 thread가 없을 때 생긴다.