ข้ามไปยังเนื้อหา

Async & Concurrency — ภาพรวม

JavaScript ทำงานบน thread เดียว มี call stack เดียว event loop เดียว และไม่มีการแชร์ memory ระหว่าง concurrent units of work เมื่อคุณเขียน async/await ใน Node.js คุณกำลัง schedule microtasks บน thread เดียวนั้น — ไม่มีการทำสองสิ่งพร้อมกันจริงๆ ภายใน process เดียว

Python ให้คุณ เครื่องมือ concurrency สามอย่าง และคุณต้องเลือกให้เหมาะกับงาน:

เครื่องมือคืออะไรเหมาะกับ
asyncioCooperative concurrency แบบ single-threadedโค้ด I/O-bound async (HTTP, DB, ไฟล์)
threadingOS threads ที่แชร์ interpreter เดียวกันโค้ด I/O-bound, library แบบ blocking เก่า
multiprocessingSeparate OS processesงาน CPU-bound ที่ต้องการ parallelism จริงๆ

คำสองคำนี้มักถูกนำมาใช้แทนกัน แต่ความหมายต่างกัน:

  • Concurrency — หลาย task อยู่ระหว่างดำเนินการ ในเวลาเดียวกัน แต่ไม่จำเป็นต้อง execute พร้อมกันทุกนาที event loop สลับระหว่าง task เมื่อ task หนึ่งกำลังรอ นี่คือวิธีที่ Node.js ทำงาน และวิธีที่ asyncio ของ Python ทำงาน
  • Parallelism — หลาย task execute พร้อมกันทุกขณะบน CPU core ต่างกัน สิ่งนี้ต้องการหลาย OS process ใน Python (หรือหลาย thread ในภาษาอื่นๆ ส่วนใหญ่)
TypeScript
// JavaScript/Node.js
// Concurrency via the event loop — single thread, never truly parallel
async function fetchUser(id: number): Promise<User> {
// While this awaits, other promises can run
return await db.query("SELECT * FROM users WHERE id = $1", [id]);
}
// Promise.all is concurrent, not parallel — still one thread
const [user, posts] = await Promise.all([
fetchUser(1),
fetchPosts(1),
]);
Python
# Python
# asyncio — same single-threaded cooperative model as JS
import asyncio
async def fetch_user(user_id: int) -> dict:
# While this awaits, other coroutines can run
await asyncio.sleep(0) # yield to event loop
return {"id": user_id}
# asyncio.gather — same idea as Promise.all
async def main() -> None:
user, posts = await asyncio.gather(
fetch_user(1),
fetch_posts(1),
)
TypeScript
// JavaScript has one model: event loop + Web Workers for threads
// One thread for JS logic, workers for CPU work (separate memory)
// Main thread
const worker = new Worker("worker.js");
worker.postMessage({ data: bigArray });
worker.onmessage = (e) => console.log(e.data);
Python
# Python has three models
import asyncio # like Node's event loop
import threading # OS threads (limited by GIL — see below)
import multiprocessing # true parallelism, separate memory
# Pick based on your bottleneck:
# waiting on network/disk → asyncio or threading
# heavy CPU math → multiprocessing
flowchart TD
  io{"Bottleneck is waiting on I/O? (network, disk, DB)"}
  cpu{"Bottleneck is CPU computation? (math, image, ML)"}
  simple{"Just want a simple high-level API?"}
  io -- Yes --> asyncio["Use asyncio (preferred) or threading"]
  io -- No --> cpu
  cpu -- Yes --> mp["Use multiprocessing (bypasses the GIL)"]
  cpu -- No --> simple
  simple -- Yes --> cf["Use concurrent.futures (wraps threading and multiprocessing)"]
Choosing a concurrency tool

บทเรียนที่เหลือในโมดูลนี้จะครอบคลุมแต่ละเครื่องมืออย่างละเอียด

ความแตกต่างหลักระหว่าง concurrency และ parallelism คืออะไร?
ควรเลือกเครื่องมือ Python ใดสำหรับงาน CPU-bound ที่ต้องการ parallelism จริงๆ?
ทำไม Python thread จึงไม่ได้ parallelism สำหรับงาน CPU-bound?
concept ของ JavaScript ใดที่เปรียบเทียบได้ใกล้เคียงที่สุดกับ asyncio ของ Python?