Giới thiệu về Đồng thời trong Go
Đồng thời là một khía cạnh quan trọng của phát triển phần mềm hiện đại vì nó cho phép các chương trình xử lý đồng thời nhiều tác vụ một cách hiệu quả. Bạn có thể viết các chương trình thực thi các hoạt động khác nhau để cải thiện hiệu suất, khả năng phản hồi và sử dụng tài nguyên.
Đồng thời là một trong những tính năng chịu trách nhiệm cho việc áp dụng nhanh chóng của Go. Hỗ trợ tích hợp sẵn của Go cho lập trình đồng thời được coi là đơn giản đồng thời giúp tránh những cạm bẫy phổ biến như điều kiện chủng tộc và bế tắc.
Mục Lục
Đồng thời trong Go
Go cung cấp khả năng hỗ trợ đồng thời mạnh mẽ thông qua nhiều cơ chế khác nhau, tất cả đều có sẵn trong thư viện và chuỗi công cụ tiêu chuẩn của nó. Các chương trình Go đạt được sự đồng thời thông qua các goroutine và các kênh.
Các goroutine rất nhẹ, thực thi các chức năng độc lập chạy đồng thời với các goroutine khác trong cùng một không gian địa chỉ. Goroutines cho phép nhiều tác vụ tiến hành đồng thời mà không cần quản lý luồng rõ ràng. Các goroutine nhẹ hơn các luồng của hệ điều hành và Go có thể chạy hàng nghìn hoặc thậm chí hàng triệu goroutine đồng thời một cách hiệu quả.
Các kênh là cơ chế giao tiếp để phối hợp và chia sẻ dữ liệu giữa các goroutine. Kênh là một ống dẫn được nhập cho phép các goroutine gửi và nhận các giá trị. Các kênh cung cấp khả năng đồng bộ hóa để đảm bảo chia sẻ dữ liệu an toàn giữa các goroutine đồng thời ngăn chặn các điều kiện tương tranh và các vấn đề tương tranh phổ biến khác.
Bằng cách kết hợp các goroutine và các kênh, Go cung cấp một mô hình đồng thời mạnh mẽ và đơn giản giúp đơn giản hóa việc phát triển các chương trình đồng thời trong khi vẫn duy trì sự an toàn và hiệu quả. Các cơ chế này cho phép bạn dễ dàng sử dụng bộ xử lý đa lõi và xây dựng các ứng dụng có khả năng mở rộng và đáp ứng cao.
Cách sử dụng Goroutines để thực thi mã đồng thời
Thời gian chạy Go quản lý các goroutine. Goroutine có ngăn xếp của chúng, cho phép chúng có dung lượng nhẹ với kích thước ngăn xếp ban đầu là vài kilobyte.
Các Goroutine được ghép vào một số luồng hệ điều hành bằng thời gian chạy Go. Bộ lập lịch thời gian chạy Go lên lịch chúng vào các luồng có sẵn bằng cách phân bổ khối lượng công việc một cách hiệu quả, cho phép thực thi đồng thời nhiều goroutine trên ít luồng hệ điều hành hơn.
Tạo goroutines rất đơn giản. Bạn sẽ sử dụng đi từ khóa theo sau là lệnh gọi hàm để khai báo goroutines.
func main() {
go function1()
go function2()
}
func function1() {
}
func function2() {
}
Khi chương trình gọi hàm1() Và hàm2() với đi từ khóa, thời gian chạy Go thực thi các chức năng đồng thời dưới dạng goroutines.
Đây là một ví dụ sử dụng goroutine in văn bản ra bàn điều khiển:
package mainimport (
"fmt"
"time"
)
func printText() {
for i := 1; i <= 5; i++ {
fmt.Println("Printing text", i)
time.Sleep(1 * time.Second)
}
}
func main() {
go printText()
for i := 1; i <= 5; i++ {
fmt.Println("Performing other tasks", i)
time.Sleep(500 * time.Millisecond)
}
time.Sleep(6 * time.Second)
}
Các in văn bản chức năng liên tục in một số văn bản tới bàn điều khiển với một vì vòng lặp chạy năm lần sau độ trễ một giây giữa mỗi câu lệnh với gói thời gian.
Các chủ yếu chức năng bắt đầu một goroutine bằng cách gọi đi in văn bảnkhởi chạy in văn bản chức năng như một goroutine đồng thời riêng biệt cho phép chức năng thực thi đồng thời với phần còn lại của mã trong chủ yếu chức năng.
Cuối cùng, để đảm bảo rằng chương trình không thoát trước khi in văn bản goroutine kết thúc, các thời gian ngủ chức năng tạm dừng goroutine chính trong sáu giây. Trong các tình huống trong thế giới thực, bạn sẽ sử dụng các cơ chế đồng bộ hóa như kênh hoặc nhóm chờ để điều phối việc thực thi goroutine.
Sử dụng các kênh để liên lạc và đồng bộ hóa
Goroutine có hỗ trợ tích hợp cho giao tiếp và đồng bộ hóa thông qua các kênh, giúp việc viết mã đồng thời dễ dàng hơn so với các luồng truyền thống, thường yêu cầu các cơ chế đồng bộ hóa thủ công như khóa và semaphores.
Bạn có thể coi các kênh là đường dẫn cho luồng dữ liệu giữa các goroutine. Một goroutine có thể gửi một giá trị vào kênh và một goroutine khác có thể nhận giá trị đó từ kênh. Cơ chế này đảm bảo việc trao đổi dữ liệu được an toàn và đồng bộ.
Bạn sẽ sử dụng <- nhà điều hành để gửi và nhận dữ liệu thông qua các kênh.
Đây là một ví dụ minh họa cách sử dụng cơ bản các kênh để liên lạc giữa hai goroutine:
func main() {
ch := make(chan string)
go func() {
ch <- "Hello, Channel!"
}()
msg := <-ch
fmt.Println(msg)
}
Kênh trong chủ yếu chức năng là một kênh không có bộ đệm có tên ch được tạo ra với làm() chức năng. Con goroutine đầu tiên gửi thông báo “Xin chào, Kênh!” vào kênh bằng cách sử dụng <- toán tử và goroutine thứ hai nhận tin nhắn từ kênh bằng cùng một toán tử. cuối cùng chủ yếu chức năng in tin nhắn nhận được ra bàn điều khiển.
Bạn có thể xác định các kênh đã nhập. Bạn sẽ chỉ định loại kênh khi tạo. Đây là một ví dụ minh họa việc sử dụng các loại kênh khác nhau:
func main() {
ch1 := make(chan int)
ch2 := make(chan string, 3)
ch1 <- 42
value1 := <-ch1
ch2 <- "Hello"
value2 := <-ch2
}
Các chủ yếu chức năng tạo hai kênh: ch1 là một kênh số nguyên không có bộ đệm, trong khi ch2 là một kênh chuỗi đệm có dung lượng là 3. Bạn có thể gửi và nhận các giá trị đến và từ các kênh này bằng cách sử dụng <- toán tử (các giá trị phải thuộc loại được chỉ định).
Bạn có thể sử dụng các kênh làm cơ chế đồng bộ hóa để điều phối việc thực thi goroutine bằng cách tận dụng tính chất chặn của hoạt động kênh.
func main() {
ch := make(chan bool) go func() {
fmt.Println("Goroutine 1")
ch <- true
}()
go func() {
<-ch
fmt.Println("Goroutine 2")
}()
<-ch
fmt.Println("Main goroutine")
}
Các ch kênh là boolean. Hai goroutines chạy đồng thời trong chủ yếu chức năng. Goroutine 1 báo hiệu sự hoàn thành của nó bằng cách gửi một ĐÚNG VẬY giá trị vào kênh ch. Goroutine 2 đợi tín hiệu hoàn thành bằng cách nhận giá trị từ kênh. Cuối cùng, goroutine chính đợi tín hiệu hoàn thành từ goroutine hai.
Bạn có thể xây dựng các ứng dụng web ngay lập tức với Gin
Bạn có thể xây dựng các ứng dụng web hiệu suất cao trong Go with Gin đồng thời tận dụng các tính năng đồng thời của Go.
Bạn có thể sử dụng Gin để xử lý định tuyến HTTP và phần mềm trung gian một cách hiệu quả. Tận dụng khả năng hỗ trợ đồng thời tích hợp sẵn của Go bằng cách sử dụng các goroutine và kênh cho các tác vụ như truy vấn cơ sở dữ liệu, lệnh gọi API hoặc các hoạt động chặn khác.