Golang toàn tập – Goroutines và Channels

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Được biết tới là một trong những ngôn ngữ hỗ trợ mạnh mẽ concurrency, Golang Goroutines và Channels thật ra có ý nghĩa như thế nào?. Có sự khác biệt nào giữa Golang Concurrency và Java Concurrency hay không?.

  Channel trong Golang là gì? So sánh Callback function và mutex lock với channel
  Golang là gì và tại sao bạn nên học Go?

Trước khi bắt đầu tìm hiểu sâu hơn, hãy cùng bắt đầu với hai khái niệm cơ bản nhất, Routines và Channels.

goroutines và channelsA hero – Goroutines with channel

Ngoài ra, golang cũng hỗ trợ functional programming. Có thể tìm hiểu qua về functional programming qua bài viết này.

Ok, bắt đầu ngay thôi!

1. Concurrency

Trước khi bắt đầu tìm hiểu Routines và Channels, hãy nắm bắt khái niệm về Concurrency (Tính toán đồng thời).

Making process on more than one task simultaneously is known as concurrency

Việc thực hiện nhiều hơn một task trên một process được biết tới là concurrency (đồng thời, cùng lúc)

Đã hiểu về Concurrency, tuy nhiên nhớ take note luôn là nó khác biệt hoàn toàn với Parallel. Thực hiện mọi việc đồng thời, nhưng có thể chỉ ở trên cùng một core, một process của CPU.

Parallel lại tận dụng đa lõi, thực hiện mọi việc đồng thời, nhưng trên nhiều tiến trình.

Sự khác biệt giữa concurrency và parallelNguồn ảnh / Source: ednsquare.com

2. Goroutines

Muốn một function có thể chạy đồng thời với function tất nhiên phải có khai báo. Không khai báo thì Go không thể biết được khi nào function đó được chạy Concurrency.

A goroutine is a function that is capable of running concurrently with other functions

Goroutine là function có thể chạy đồng thời với các function khác

Để khai báo một function sử dụng Routines, ta dùng từ khóa go.

// Function go f(0) được thực hiện đồng thời
package main
import "fmt"
func f(n int) { 
for i := 0; i < 10; i++ { 
fmt.Println(n, ":", i) 
} 
}
func main() { 
go f(0) 
var input string 
fmt.Scanln(&input) 
}

Đoạn code vừa viết phía trên có tới hai Goroutines. Cái đầu tiên tất nhiên là function main, tự bản thân nó đã là một Goroutines. Cái thứ hai sẽ được khởi tạo khi ta gọi function go f(0).

Ở các chương trình Java thông thường (hoặc Golang mà không có sử dụng từ khóa go). Dòng code số 11 sẽ được thực thi sau khi function f(0) hoàn tất. Nhưng với Routines, các dòng code từ dòng 11 trở đi vẫn được thực thi cùng lúc với function f (0)

// Chỉ với từ khóa go, đoạn code dưới đây tạo ra tới 10 Goroutines
func main() { 
for i := 0; i < 10; i++ { 
go f(i) 
} 
var input string 
fmt.Scanln(&input) 
}

Chốt hạ “The goroutines run simultaneously. – Goroutines chạy đồng thời”

3. Channels

Chỉ với từ khóa go, rõ ràng mà nói, tạo nhiều Goroutines không hề khó. Nhưng nếu các Goroutines muốn giao tiếp với nhau. Routines này chạy đồng bộ chờ kết quả routines khác?

Đấy, lúc đấy có ngay Channels.

Channels provide a way for two goroutines to communicate with each other and synchronize their execution

Channels cung cấp cách thức cho phép các goroutines giao tiếp với nhau và thực hiện đồng bộ hóa

Đối với channel, chiều gửi dữ liệu tuần theo chiều của mũi tên.

// Chỉ cần chú ý variable bên phải là bên gửi.
ch <- v // Gửi giá trị v tới channels ch
v := <-ch // Nhận giá trị từ channel ch, gán cho v.

Cũng giống như maps và slices, channels được khởi tạo ngay sao khi khai báo từ khóa chan.

ch := make(chan int)

Mặc định, việc gửi hay nhận ở goroutines này sẽ bị block cho tới khi goroutines khác thực hiện xong. Ví dụ dưới đây thực hiện tính toán đồng thời trên mảng s, cả hai routines sẽ thực hiện xong và cho kết quả cuối cùng.

package main

import "fmt"

func sum(s []int, c chan int) {
sum := 0
sum += s[0]
c <- sum // Gán tổng c cho sum
}

func main() {
s := []int{7, 2, 8, -9, 4, 0}

c := make(chan int)

// Mảng s ở routines này là [-9, 4, 0]
go sum(s[:len(s)/2], c)
// Mảng s ở routines này là [7, 2, 8, -9]
go sum(s[len(s)/2:], c)

x, y := <-c, <-c // Nhận giá trị từ c

fmt.Println(x, y, x+y)
}

Channels c sau khi chạy sẽ in ra kết quả là:

// Thực hiện tuần tự sum 1 cho tới sum 2
-9 7 -2

Program exited.

Xong, bài viết này cho thấy một cái nhìn tổng quan nhất về Concurrency trong Golang. Nếu có bất cứ câu hỏi hoặc phản hồi gì, vui lòng comment bên dưới bài viết.

4. Tham khảo

Cảm ơn vì đã đọc bài. Happy coding!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev