Preview Bản nháp chờ review — title, nội dung, link có thể sửa trước khi bỏ nhãn.

Coroutine / await nhường runner. Event loop chỉ chạy tiếp việc khác khi đoạn hiện tại chịu nhường. Đó là cooperative scheduling.

OS thread thì khác: preemptive — scheduler có thể cắt giữa chừng (time slice), task không cần gọi await.

Hai mô hình

Cooperative
  · Task tự yield (await, yield, channel recv…)
  · Giữa hai yield: ôm CPU/stack một mình
  · Starvation nếu ai đó không yield

Preemptive
  · OS/runtime cắt theo policy
  · Fair hơn với CPU-bound lẫn lộn
  · Context switch đắt hơn; shared memory race dễ hơn

Hệ quả production

  • JS/Node: tight loop / JSON lớn / crypto sync = không yield = kẹt cả loop (mọi await ready cũng đứng).
  • Cancel cooperative: không check signal = không dừng.
  • Thread pool preemptive: một job CPU không chặn thread khác trên core khác — nhưng shared lock vẫn block.
  • Go: goroutine trông cooperative; runtime có preemption tại safepoint — “lai”.

Starvation — ví dụ

// Ôm loop: không await → không ai khác chạy
while (Date.now() < end) { crunch() }

// “Hơi” cooperative nhưng microtask đói timer
function spin() {
  Promise.resolve().then(spin) // không nhường macrotask
}
spin()

Xem event loop — microtask drain và sync block.

Khi nào cooperative đủ

I/O-bound, code hay await, đoạn sync ngắn. Đúng chỗ dealing with trên ít thread.

Khi cần preemption / offload

CPU dài, thư viện sync, không tin mọi path sẽ yield → offload, process riêng, parallel doing.

Một câu

Cooperative chỉ công bằng khi mọi người thật sự nhường.
Preempt cắt giúp fairness CPU — đổi lấy chi phí và race.