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

การทำงานพร้อมกัน — ภาพรวม

ในฐานะนักพัฒนา TypeScript/Node.js คุณใช้ชีวิตอยู่กับ event loop โค้ด JS ทั้งหมดรันบน thread เดียว และ “concurrency” ที่คุณเห็นคือการสลับ context ไปมาระหว่าง callbacks, Promises และ async/await — ไม่ใช่ parallelism จริง

Go ต่างออกไปโดยสิ้นเชิง Go runtime จะ schedule goroutines ลงบน OS threads จริงหลายตัว goroutine หลายตัวจึงรันพร้อมกันได้จริงบน CPU คนละ core โดยไม่ต้องพึ่ง Worker Threads

Rob Pike (หนึ่งในผู้สร้าง Go) อธิบายไว้ได้ชัดเจนว่า:

  • Concurrency คือการจัดการหลายสิ่งพร้อมกัน — เป็นเรื่องของโครงสร้าง
  • Parallelism คือการทำหลายสิ่งพร้อมกันจริง — เป็นเรื่องของการรัน

เชฟที่สับผักไปตอนที่น้ำกำลังเดือด = concurrent (จัดการหลายอย่างพร้อมกัน) ส่วนเชฟสองคนทำงานเคียงข้างกันในครัวเดียว = parallel (ทำหลายอย่างพร้อมกันจริง)

Node.js เก่งเรื่อง concurrency (non-blocking I/O) แต่ทำ parallelism จริงไม่ได้ถ้าไม่ใช้ Worker Threads หรือแยกหลาย process ส่วน Go รองรับทั้งสองอย่างได้ในตัว

TypeScript
// JavaScript: single-threaded event loop
// "concurrency" through callbacks / Promises
async function fetchData(url: string) {
const res = await fetch(url); // yields to event loop
return res.json();
}
// setTimeout / setInterval schedule callbacks on the loop
setTimeout(() => console.log("later"), 0);
console.log("first"); // always prints before "later"
Go
// Go: real concurrent goroutines
// Each 'go' spawns a lightweight thread managed by Go runtime
package main
import (
"fmt"
"sync"
)
func fetchData(url string, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Fetching:", url) // runs concurrently
}
func main() {
var wg sync.WaitGroup
urls := []string{"api/users", "api/orders", "api/products"}
for _, url := range urls {
wg.Add(1)
go fetchData(url, &wg)
}
wg.Wait() // block until all goroutines finish
}
  • Goroutinesgo f() สร้าง goroutine ได้ทันที; เปรียบเทียบกับ async functions
  • Channels — ท่อส่งข้อมูลระหว่าง goroutines; เปรียบเทียบกับ Promises/callbacks
  • Select — เลือกจากหลาย channels พร้อมกัน; เปรียบเทียบกับ Promise.race
  • SyncWaitGroup, Mutex, RWMutex สำหรับ shared state
  • Context — cancellation และ deadlines; เปรียบเทียบกับ AbortController
  • Worker Pools — pattern สำหรับจัดการงานพร้อมกันอย่างมีประสิทธิภาพ
package main
import (
"fmt"
"sync"
)
func task(name string, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Task %s running\n", name)
}
func main() {
var wg sync.WaitGroup
tasks := []string{"A", "B", "C"}
for _, t := range tasks {
wg.Add(1)
go task(t, &wg)
}
wg.Wait()
fmt.Println("All tasks complete")
}
อะไรคือความแตกต่างหลักระหว่าง concurrency และ parallelism?
JavaScript ทำงานบนกี่ thread โดยค่าเริ่มต้น?
Goroutine stack เริ่มต้นมีขนาดเท่าไหร่?