L27 — Goroutine và Channel
Ba module tương tác minh hoạ ba "khái niệm sống" của concurrency trong Go: (1) Go scheduler nuôi hàng vạn goroutine trên vài OS thread, (2) channel làm khớp nối giữa goroutine, (3) worker pool — pattern phổ thông kết hợp cả hai.
Module 1 — Go scheduler (M:N)
Mỗi OS thread (P/M) là một "công nhân" CPU thật. Go runtime nuôi một hàng đợi run queue cho mỗi thread, và đẩy goroutine (G, ~2 KB stack) lên đó. Khi 1 thread hết việc, nó steal goroutine từ thread khác → tận dụng tối đa CPU.
2 KB (growable), OS thread stack ≈ 1–8 MB.
10 000 goroutine ≈ 20 MB RAM; 10 000 OS thread ≈ ~80 GB RAM (∞).
Khi
N nhỏ (vài thread) + M rất lớn (vạn goroutine), mô hình M:N "ép" mọi
goroutine xếp hàng trên vài run queue, switch trong user-space (~100 ns) thay vì
kernel call (~1 µs).
Module 2 — Channel handoff
Channel = ống dẫn dữ liệu giữa hai goroutine. Unbuffered: gửi/nhận phải gặp nhau (rendezvous) → một bên đi trước sẽ block. Buffered (cap N): có "kho" N slot, sender chỉ block khi đầy, receiver chỉ block khi rỗng.
0) + ok = false.
Module 3 — Worker pool
Pattern kinh điển: 1 channel jobs, N worker goroutine cùng range
trên jobs → Go runtime tự phân phối (load balance). Tăng N → throughput tăng cho tới khi
chạm trần CPU (hoặc bottleneck I/O).