- Blocking I/O: thread gọi thao tác I/O (đọc file, query DB, gọi HTTP) phải đứng chờ đến khi có kết quả — trong lúc đó không làm được việc khác.
- Non-blocking I/O: lời gọi trả về ngay; kết quả được báo lại qua callback/event khi sẵn sàng, thread rảnh để xử lý việc khác.
Hai mô hình xử lý nhiều request đồng thời:
- Thread-per-request (Java servlet truyền thống, PHP-FPM): mỗi request một thread, code viết tuần tự dễ đọc, blocking không sao vì các thread khác vẫn chạy. Chi phí: mỗi thread tốn bộ nhớ stack + context switch — hàng chục nghìn kết nối đồng thời trở nên tốn kém.
- Event loop (Node.js, Nginx): một thread chạy vòng lặp sự kiện + non-blocking I/O; hàng nghìn kết nối chỉ là các entry chờ sự kiện, rất rẻ với workload I/O-bound. Đổi lại, một tác vụ CPU-bound (tính toán nặng, parse JSON khổng lồ) sẽ chặn toàn bộ loop — mọi request khác phải chờ; cần đẩy sang worker thread/process riêng.
Hướng mới: virtual thread (Java 21) / goroutine (Go) cho phép viết code kiểu blocking nhưng runtime lo phần non-blocking bên dưới.