Một trong những khía cạnh phổ biến nhất của ngôn ngữ lập trình Go là khả năng hỗ trợ hạng nhất của nó đối với khả năng của máy tính để hoàn thành nhiều tác vụ cùng một lúc. Khả năng chạy mã đồng thời đang trở nên quan trọng hơn trong lập trình khi máy tính chuyển từ thực thi một luồng mã nhanh hơn sang chạy nhiều luồng đồng thời. Để làm cho các chương trình chạy nhanh hơn, các lập trình viên phải thiết kế để chúng chạy đồng thời sao cho mỗi phần tử đồng thời của hệ thống có thể thực thi độc lập với các phần tử khác.
Hai chức năng Go, Goroutines và các kênh giúp đồng thời dễ dàng hơn khi được sử dụng cùng nhau. Goroutines cung cấp kiểu nguyên thủy cơ bản cho khả năng này. Goroutines ít tốn kém hơn về không gian bộ nhớ, tương tác giữa các luồng và kết nối mạng. Chúng cũng có thời gian khởi động tốt hơn các luồng mà nhiều ngôn ngữ lập trình hỗ trợ. Về bản chất, Go đề cập đến Goroutines như những gì Java và các ngôn ngữ lập trình khác gọi là luồng.
Goroutines là gì?
Một goroutine là một luồng triển khai đơn giản trong Golang thực hiện đồng thời với phần còn lại của chương trình. Goroutines có giá cả phải chăng khi giống với các luồng tiêu chuẩn vì chi phí tạo một goroutine là cực kỳ thấp. Do đó, chúng được sử dụng rộng rãi trong Go để lập trình đồng thời. Mỗi chương trình bao gồm ít nhất một goroutine duy nhất được gọi là goroutine chính. Con goroutine chính kiểm soát tất cả các con goroutine khác; do đó, nếu goroutine chính kết thúc, tất cả các goroutine khác trong tập lệnh cũng vậy. Goroutine luôn hoạt động ở chế độ nền.
Ví dụ: Đây là một minh họa: bạn đang viết gì đó vào sổ tay và cảm thấy đói; bạn sẽ nghỉ ngơi và lấy một ít thức ăn. Sau đó bắt đầu viết lại. Bạn hiện đang làm hai vai trò (viết và ăn) trong khoảng thời gian được coi là công việc kiêm nhiệm. Cần nhấn mạnh rằng hai nhiệm vụ này (viết và ăn) vẫn cần được hoàn thành đồng thời. Khi các mục được hoàn thành đồng thời, nó được gọi là song song (hãy tưởng tượng bạn vừa sử dụng điện thoại di động vừa nhai chip). Đồng thời bao gồm tương tác với nhiều thứ cùng một lúc. Song song (thực hiện nhiều việc đồng thời) là một lớp con của điều này (không phải thực hiện cùng một lúc) với một số thời gian biểu.
Chúng ta có thể thêm một goroutine bằng cách áp dụng từ khóa go cho lệnh gọi hàm. Khi chúng tôi áp dụng từ khóa go cho cuộc gọi chức năng, chúng tôi sẽ đặt đồng thời cho hiệu suất. Nhưng trước tiên, hãy xác định tác dụng của việc áp dụng từ khóa go vào việc thực thi. Hãy xem xét có hai goroutine trong một chương trình. Dòng chữ " package main import " sẽ là mục nhập của chương trình. Trong Go, nhập gói chính là câu lệnh nhập khai báo. Các goroutine chính ( goroutine first goroutine) được ngụ ý. Khi chúng ta thực thi go ( f), goroutine thứ hai được hình thành (0). Thông thường, phần mềm của chúng tôi sẽ thực thi mọi lệnh trong chức năng chính khi chúng tôi thực thi một chức năng trước khi chuyển sang dòng tiếp theo.
Chúng ta có thể chạy thủ tục nhanh chóng bằng goroutine trước khi chuyển sang bước tiếp theo. Kết quả là, một phương thức scanln đã được thêm vào; nếu không, mã sẽ kết thúc trước khi hiển thị tất cả các số. Goroutines rất đơn giản để tạo và có thể được tạo với số lượng lớn. Bạn sẽ nhận thấy rằng khi phần mềm này được chạy, các goroutine dường như hoạt động tuần tự thay vì đồng thời.
Ưu điểm của Goroutines so với luồng
Goroutines tốn ít chi phí
Goroutines ít tốn kém hơn so với các quy trình khác. Kích thước khối chỉ là vài kilobyte và nó có thể mở rộng hoặc co lại để đáp ứng nhu cầu của chương trình, trái ngược với các luồng có kích thước ngăn xếp phải được xác định và là vĩnh viễn.
Có các Goroutines đa kênh
Có rất ít luồng hệ điều hành mà chúng được ghép kênh. Trong một chương trình có hàng trăm goroutine, có thể chỉ có một process. Phần còn lại của các goroutine được chuyển sang quy trình hệ điều hành mới. Ví dụ, giả sử bất kỳ goroutine nào trong quy trình đó bị kẹt khi nó đang tìm kiếm sự can thiệp của người dùng. Thời gian chạy quản lý từng thứ này và các nhà phát triển của chúng tôi được cung cấp một API rõ ràng để quản lý đồng thời trong khi được cách ly khỏi những điều phức tạp tinh tế này.
Goroutines giao tiếp bằng cách sử dụng các kênh
Goroutines trò chuyện bằng cách sử dụng các kênh. Dự định ngăn chặn các tình huống cuộc đua xảy ra khi chúng chia sẻ bộ nhớ liên quan. Các kênh có thể được so sánh với một ống dẫn mà goroutines sử dụng để tương tác.
Các kênh là gì?
Hai goroutine có thể tương tác với nhau và phối hợp hoạt động của chúng trên các kênh. Phần mềm này sẽ liên tục in ra tiếng " ping ". Để chỉ định dạng kênh, tiền tố " chan " được đi kèm với các mục được truyền trên kênh." Trong trường hợp này, chúng tôi đang cung cấp các chuỗi. Trên kênh, tin nhắn được gửi và nhận bằng toán tử. " ping " đề cập đến việc gửi một tiếng " ping ".
Một kênh được sử dụng để giữ cho hai goroutine đồng bộ. Trước khi thử gửi tin nhắn qua kênh, bộ định tuyến sẽ đợi cho đến khi máy in sẵn sàng chấp nhận tin nhắn đó. Thuật ngữ cho điều này là ức chế. Khi tạo kênh, tham số thứ hai có thể được sử dụng cho hàm tạo: c:= make (chan int, 1)
Hướng của kênh
Chúng ta có thể xác định hướng và tham số của biểu mẫu kênh để nhận hoặc truyền. Chẳng hạn, ký hiệu phương thức của Pinger có thể được thay đổi thành:
func pinger(c chan<- string)
C chỉ có thể được gửi bây giờ. Nhận từ c sẽ bị lỗi code. Tương tự, chúng tôi có thể sửa đổi đầu ra thành:
func printer(c string -chan)
Một bán kênh không có những ràng buộc này. Một kênh hai hướng có thể được cung cấp cho một thủ tục chỉ chấp nhận các kênh chỉ truyền hoặc chỉ chấp nhận, chứ không phải theo cách khác.
Làm thế nào để tạo một Goroutine?
Phương pháp khởi chạy một goroutine rất đơn giản. Áp dụng từ khóa " go " cho lệnh gọi hàm để tạo một goroutine sẽ thực thi đồng thời. Ở đây chúng ta sẽ tạo một goroutine. Giả sử chúng ta có một chương trình chứa hai chức năng: một là chức năng chào mừng và chức năng kia là chức năng chính.
Khi chúng ta tạo một goroutine mới, code welcome() sẽ thực thi cùng với hàm main(). Khi bạn thực hiện chương trình này, bạn sẽ ngạc nhiên. Chương trình này chỉ hiển thị văn bản hoạt động chính. Điều gì đã xảy ra với goroutine đầu tiên hoặc goroutine mới mà chúng tôi đã khởi tạo? Để hiểu tại sao điều này xảy ra, trước tiên chúng ta phải biết hai tính năng chính của goroutine.
- Chức năng goroutine phản hồi ngay lập tức khi chúng ta tạo một goroutine mới. Ngoài các chức năng, việc quản lý không dựa vào goroutine, vì vậy nó không đợi goroutine hoàn thành việc thực thi. Việc thực thi được trao cho khối mã sau sau chức năng goroutine. Đây là lý do tại sao mọi tham số đã cho từ goroutine đều bị bỏ qua.
- Mọi goroutine bổ sung sẽ chạy đồng thời với goroutine chính. Nếu goroutine chính bị lỗi, chương trình sẽ thoát và không có goroutine bổ sung nào được chạy.
Bây giờ bạn đã hiểu tại sao mã của chúng tôi không hoạt động. Sau lời gọi go welcome(), quyền điều khiển được chuyển sang dòng mã sau trước khi đợi hello goroutine hoàn thành và chức năng chính được xuất ra. Goroutine chính chết vì không có tập lệnh nào để thực hiện, ngăn cản hello Goroutine chạy.
Chúng tôi đã gọi kỹ thuật ngủ ( time.sleep(1 * time.second)) để tạm dừng goroutine trong 1 giây. Chức năng go welcome() hiện có đủ thời gian để hoàn thành trước khi thoát khỏi goroutine chính. Ban đầu, phần mềm này viết " welcome goroutine " và sau đó đợi một giây trước khi in chức năng chính. Chúng tôi sử dụng kỹ thuật ngủ trong goroutine chính để tạm dừng nó trong giây lát để các goroutine khác hoàn thành.
Tạo nhiều Goroutines
Chúng ta sẽ bắt đầu một chương trình khác để tạo nhiều goroutine. Trước tiên, chúng ta có thể bắt đầu bằng cách tạo hai goroutine sẽ thực thi song song. Hai con khỉ đột này là con khỉ đột số[go numbers()] và con khỉ đột bảng chữ cái [ go alphabets ()].
Con goroutine số giữ nguyên trong 250 mili giây trước khi in 1, nghỉ một lần nữa trước khi in 2, v.v. cho đến khi nó tạo ra 5. Tương tự, goroutine chữ và số hiển thị chữ cái từ a đến e và sau đó đợi 400 mili giây. Cuối cùng, goroutine chính tạo ra các số nguyên và ký tự chữ và số và tạm dừng trong một khoảng thời gian ngắn, sau đó goroutine chính kết thúc.
Các lỗi lập trình đồng thời thường gặp
- Không có đồng bộ hóa khi điều này là bắt buộc
- Sử dụng thời gian. Cuộc gọi ngủ để thực hiện đồng bộ hóa
- Để lại các giá trị bản sao lủng lẳng của goroutines của các loại trong gói đồng bộ hóa tiêu chuẩn
- Gọi đồng bộ hóa
- nhóm chờ
- Thêm phương thức ở những nơi sai
- Sử dụng các kênh như các kênh đóng vào ngày mai, không phải từ goroutine người gửi chức năng cuối cùng
Sự kết luận
Trong bài viết này, chúng tôi đã phát triển một chương trình sử dụng từ khóa go để khởi chạy một goroutine và nhiều goroutine đồng thời in các số nguyên. Sau khi bắt đầu chương trình đó, chúng tôi đã thiết lập một kênh mới, sau đó chúng tôi sử dụng kênh này để tạo các số trong một con khỉ đột và chuyển chúng sang một con khỉ đột khác để chúng có thể được hiển thị trên màn hình. Như một minh chứng cuối cùng về cách bắt đầu một goroutine để tăng tốc các ứng dụng của bạn trên các hệ thống đa lõi, bạn đã khởi chạy đồng thời nhiều goroutine "in".
Như chúng ta đã biết, goroutines là một cách để thực hiện các tác vụ nhanh hơn và hiệu quả hơn. Đây là một trong những quy trình triển khai do AppMaster cung cấp để cải thiện chức năng của ứng dụng của bạn. Với AppMaster, ngay cả những người có ít hoặc không có kiến thức lập trình cũng có thể hoàn thành các tác vụ khó hoàn thành thông qua viết mã thủ công.
AppMaster là một nền tảng no-code có thể tạo các ứng dụng web và di động cũng như phần phụ trợ. Một sự thật thú vị là AppMaster tạo một chương trình phụ trợ bằng Go với tốc độ 22.000 dòng mỗi giây và bạn có thể truy cập mã nguồn.