Anh em làm với Golang chắc hẳn đã nghe qua khác niệm Buffered Channel. Vậy Buffered Channel là gì?
Bài viết này sẽ giải thích cho anh em khái niệm Buffered Channel. Deadlock trong Buffered Channel và các ví dụ cụ thể giải thích cách Buffered Channel hoạt động.
Bắt đầu thôi anh em!
1. Buffered Channel là gì?
Tới với định nghĩa:
Channels can be defined as pipes used for Goroutines to communicate. Similar to how water flows from one end to another in a pipe, data can be sent from one end and received from the another end using channels. Channels có thể được định nghĩa là các đường dẫn được sử dụng để Goroutines giao tiếp. Tương tự như cách nước chảy từ đầu này sang đầu kia trong đường ống, dữ liệu có thể nhận vào từ đầu này và chuyển tới đầu kia thông qua channels
Rồi, dứt được một chữ Channel trong Buffered Channel. Kênh này như là cái ống, nhầm như con kênh. Dữ liệu đi vào đầu này sẽ đi ra đầu kia, như nước chảy từ đầu kênh tới cuối kênh.
Còn Buffered (bộ đệm), theo như mặc định trong Golang thì một channel tạo ra sẽ không có Buffered. Kênh không có bộ đệm sẽ chỉ gửi dữ liệu A nếu đầu kia ở channel chấp nhận dữ liệu A. Kênh Buffered Channel sẽ chỉ bị tắc khi bộ đệm full (đầy).
Đó là chiều gửi đi, còn chiều nhận về thì đầu kia của channel sẽ bị chặn dữ liệu nếu bộ đệm trống (buffered is empty).
2. Khởi tạo bộ Buffered Channel
Buffered Channel có thể được tạo bằng cách thêm parameter vào hàm make() với kích thước buffer cố định được truyền vào.
Cú pháp : ch := make(chan type, capacity) // change định nghĩa kiểu của channel
Trong cú pháp ở trên, capacity là con số cần phải lớn hơn 0, nếu channel đó muốn định nghĩa buffer. Nhưng nếu không có buffer (unbuffered channel) thì để giá trị này là 0. Cứ input cái argument này alf 0 thì auto skip vụ buffer.
Việc làm Golang Hồ Chí Minh hấp dẫn tại TopDev!
3. Ví dụ tạo buffer channel
Anh em cùng ví dụ dưới đây về tạo buffered channel.
package main import ( "fmt" ) func main() { // Tạo buffer channel // Số lượng là 2. ch := make(chan string, 2) ch <- "geeksforgeeks" ch <- "geeksforgeeks world" fmt.Println(<-ch) fmt.Println(<-ch) }
Với đoạn code này, đầu ra sẽ là
geeksforgeeks geeksforgeeks world
Số lượng buffer được tạo là 2, do đó có thể đưa vào channel 2 chuỗi string, không bị mất mát chuỗi nào và in ra kết quả.
Rồi, ví dụ đầu tiên trơn tru, đầu xuôi đuôi lọt. Cùng tới với ví dụ thứ hai khi bị block do buffer
package main import ( "fmt" "time" ) func write(ch chan int) { for i := 0; i < 4; i++ { ch <- i fmt.Println("successfully wrote", i, "to ch") } close(ch) } func main() { // Buffer này vẫn có size là 2 ch := make(chan int, 2) go write(ch) time.Sleep(2 * time.Second) for v := range ch { fmt.Println("read value", v, "from ch") time.Sleep(2 * time.Second) } }
successfully wrote 0 to ch successfully wrote 1 to ch read value 0 from ch successfully wrote 2 to ch read value 1 from ch successfully wrote 3 to ch read value 2 from ch read value 3 from ch
Anh em chú ý ở vòng for sẽ chạy từ 0 tới 3, có 4 cái đem vào channels, nhưng channel chỉ có maximum là 2. Lúc này Goroutine chỉ ghi được giá trị 0 và 1 vào trong channel ngay lập tức. Sau đó nó block cho tới khi có ít nhất 1 giá trị được đọc từ kênh ch định nghĩa như dưới đây
successfully wrote 0 to ch successfully wrote 1 to ch
Sau đó, đọc tiếp giá trị rồi sleeps trong 2 giây. Chu kì này cứ lặp đi lặp lại cho đến khi đóng ch. Cho nên mới có khúc tiếp theo được in ra
read value 0 from ch successfully wrote 2 to ch
4. Deadlock trong Buffered Channel
Deadlock cũng như khái niệm ở các ngôn ngữ khác, lock lại cho tới chết. Trong Buffered Channel được hiểu là chương trình sẽ có lỗi nghiêm trọng trong quá trình thực thi
package main import ( "fmt" ) func main() { ch := make(chan string, 2) ch <- "geeksforgeeks" ch <- "hello" ch <- "geeks" fmt.Println(<-ch) fmt.Println(<-ch) }
Như ví dụ trên đây, quá trình ghi vào channels sẽ bị chặn do kênh đã vượt quá size capacity là 2. Thông báo in ra sẽ là
fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan send]: main.main() /tmp/sandbox048494311/prog.go:11 +0x8d
5. Tham khảo
Cảm ơn anh em đã đọc bài – Thank you for your time – Happy coding!
Tác giả: Kiên Nguyễn
Xem thêm:
- Thủ thuật xử lý lỗi trong Golang
- Tìm hiểu về Graceful Shutdown, Graceful Shutdown trong Golang
- Top 20+ câu hỏi phỏng vấn Golang Developer thường gặp
Xem thêm các việc làm Developer hấp dẫn tại TopDev