1. Concurrency là gì?
Concurrency là khả năng tổ chức nhiều công việc để chúng có thể tiến triển xen kẽ hoặc đồng thời trong cùng một khoảng thời gian. Thay vì phải thực hiện tất cả công việc theo một trình tự duy nhất, chương trình có thể chuyển đổi giữa nhiều công việc đang chờ hoặc đang xử lý.
Ví dụ, một backend cần xử lý ba request cùng lúc. Nếu chương trình chỉ xử lý tuần tự, request thứ hai có thể phải chờ request thứ nhất hoàn thành, ngay cả khi request thứ nhất đang chờ database trả kết quả. Với concurrency, server có thể tiếp tục xử lý những request khác trong thời gian chờ đó.
Go hỗ trợ concurrency ngay trong ngôn ngữ thông qua goroutine, channel và các công cụ đồng bộ. Những cơ chế này giúp tổ chức chương trình có nhiều công việc mà không cần developer tự quản lý từng OS thread.
2. Phân biệt Concurrency và Parallelism
Hai khái niệm này thường đi cùng nhau nhưng không hoàn toàn giống nhau.
Concurrency nói về cách thiết kế và tổ chức nhiều công việc có thể tiến triển độc lập. Parallelism là việc thực sự thực thi nhiều công việc cùng một thời điểm, thường thông qua nhiều CPU core.
Ví dụ, một ứng dụng tải dữ liệu từ nhiều API có thể gửi request đến API A, B và C mà không cần đợi từng request hoàn thành rồi mới gửi request tiếp theo. Đây là một cách tận dụng concurrency, đặc biệt hữu ích khi thời gian xử lý chủ yếu nằm ở việc chờ network.
Go hỗ trợ cả hai. Runtime của Go quản lý và lập lịch goroutine trên các OS thread; khi cấu hình và tài nguyên cho phép, nhiều goroutine có thể thực sự chạy song song trên các CPU core.
3. Goroutine là gì?
Goroutine là một đơn vị thực thi nhẹ do Go runtime quản lý. Nó cho phép một function chạy đồng thời với phần code đã khởi chạy nó.
Trong Go, chỉ cần thêm từ khóa go trước một lời gọi function là có thể khởi chạy function đó trong một goroutine mới.
package main
import (
"fmt"
"time"
)
func sayHello() {
fmt.Println("Hello from goroutine")
}
func main() {
go sayHello()
time.Sleep(time.Second)
fmt.Println("Main finished")
}
Ở đây, go sayHello() khởi chạy sayHello() trong một goroutine riêng. Function main() tiếp tục thực thi mà không cần chờ sayHello() kết thúc ngay tại dòng đó.
Một đặc điểm quan trọng là goroutine không đồng nghĩa với OS thread. Go runtime có thể lập lịch nhiều goroutine trên một số lượng OS thread phù hợp. Điều này giúp tạo và quản lý nhiều tác vụ đồng thời thuận tiện hơn so với việc tự quản lý thread ở mức hệ điều hành.
Goroutine có tự chạy đến khi hoàn thành không?
Goroutine có thể tiếp tục chạy sau khi function khởi chạy nó đã trả về. Tuy nhiên, goroutine không được bảo đảm sẽ hoàn thành trước khi chương trình kết thúc.
Ví dụ:
func main() {
go func() {
fmt.Println("Background task")
}()
}
Khi main() kết thúc, chương trình có thể kết thúc luôn trước khi goroutine kịp in nội dung. Runtime không tự động chờ tất cả goroutine hoàn thành.
4. Tổng kết
Goroutine & Concurrency là phần cốt lõi của Go khi xây dựng các ứng dụng có nhiều công việc tiến triển đồng thời.
Goroutine cho phép chạy function độc lập; sync.WaitGroup giúp chờ các công việc hoàn thành; channel truyền dữ liệu và phối hợp giữa các goroutine; select giúp chờ nhiều hoạt động; còn mutex và các primitive trong package sync bảo vệ dữ liệu dùng chung.
Bên cạnh những cơ chế này, phải hiểu rõ race condition, deadlock và goroutine leak. Context giữ vai trò quan trọng trong việc truyền deadline và tín hiệu cancellation, đặc biệt với các tác vụ thuộc một request backend. Worker Pool là một pattern hữu ích khi cần giới hạn số lượng công việc chạy đồng thời.








Khoá học lập trình game con rắn cho trẻ em




