← Danh sách bài học
Bài 16/20
⚡ Bài 16: Goroutine (Concurrency)
🎯 Mục tiêu:
- Hiểu concurrency vs parallelism
- Tạo goroutine với từ khóa go
- Sử dụng sync.WaitGroup
- Hiểu vấn đề race condition
1. Goroutine Là Gì?
Goroutine là "lightweight thread" do Go runtime quản lý. Rất nhẹ, có thể tạo hàng nghìn goroutines mà không lo về memory.
package main
import (
"fmt"
"time"
)
func sayHello() {
fmt.Println("Hello từ goroutine!")
}
func main() {
go sayHello() // Chạy trong goroutine riêng
fmt.Println("Hello từ main!")
time.Sleep(time.Second) // Đợi goroutine chạy xong
}
2. Nhiều Goroutines
func printNumbers(name string) {
for i := 1; i <= 3; i++ {
fmt.Printf("%s: %d\n", name, i)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go printNumbers("Goroutine 1")
go printNumbers("Goroutine 2")
time.Sleep(time.Second)
}
// Output xen kẽ nhau!
3. sync.WaitGroup
WaitGroup giúp đợi nhiều goroutines hoàn thành.
package main
import (
"fmt"
"sync"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // Báo đã xong
fmt.Printf("Worker %d starting\n", id)
// Làm việc gì đó...
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // Thêm 1 vào counter
go worker(i, &wg)
}
wg.Wait() // Đợi tất cả Done
fmt.Println("All workers finished!")
}
💡 Pattern:
1.
2.
3.
1.
wg.Add(1) trước khi go2.
defer wg.Done() trong goroutine3.
wg.Wait() để đợi tất cả
4. Anonymous Goroutine
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1)
go func(n int) { // Truyền i vào
defer wg.Done()
fmt.Println("Number:", n)
}(i) // Gọi ngay với giá trị i
}
wg.Wait()
⚠️ Cẩn thận: Nếu không truyền i vào, goroutines sẽ share cùng biến i!
5. Race Condition
// SAI - có race condition!
counter := 0
for i := 0; i < 1000; i++ {
go func() {
counter++ // Nhiều goroutines đọc/ghi cùng lúc
}()
}
// counter có thể không = 1000!
// ĐÚNG - dùng sync.Mutex
var mu sync.Mutex
var counter int
for i := 0; i < 1000; i++ {
go func() {
mu.Lock()
counter++
mu.Unlock()
}()
}
📝 Tóm Tắt
go func()- tạo goroutine- Goroutine rất nhẹ (2KB stack)
sync.WaitGroup- đợi nhiều goroutinessync.Mutex- bảo vệ shared data- Cẩn thận race condition!