Jednym z najbardziej popularnych aspektów języka programowania Go jest jego pierwszorzędne wsparcie dla zdolności komputera do wykonywania wielu zadań jednocześnie. Zdolność do jednoczesnego uruchamiania kodu staje się coraz ważniejsza w programowaniu, ponieważ komputery przechodzą od szybszego wykonywania pojedynczego strumienia kodu do jednoczesnego uruchamiania wielu strumieni. Aby tworzyć programy, które działają szybciej, programiści muszą zaprojektować je do jednoczesnego działania, tak aby każdy współbieżny element systemu mógł wykonywać się niezależnie od pozostałych.
Dwie funkcjonalności Go, Goroutines oraz kanały ułatwiają współbieżność, gdy są stosowane razem. Goroutines oferuje podstawowy typ primal dla tej możliwości. Goroutines są mniej kosztowne w odniesieniu do przestrzeni pamięci, interakcji między wątkami i łączności sieciowej. Mają również lepszy czas uruchamiania niż wątki, które obsługuje wiele języków programowania. W istocie, Go odnosi się do Goroutines jako tego, co Java i inne języki programowania określają jako wątki.
Czym są Goroutines?
Goroutine to prosty wątek implementacyjny w Golangu, który wykonuje się jednocześnie z resztą programu. Goroutines są przystępne, gdy przypominają standardowe wątki, ponieważ koszt utworzenia goroutine jest niezwykle niski. Dlatego są one szeroko stosowane w Go do programowania współbieżnego. Każdy program składa się z co najmniej jednego goroutine znanego jako main goroutine. Główny goroutine kontroluje wszystkie inne goroutine; tak więc, jeśli główny goroutine kończy pracę, wszystkie inne goroutine w skrypcie również. Goroutine jest zawsze aktywny w tle.
Przykład: Oto ilustracja: piszesz coś w swoim notatniku i robisz się głodny; zrobisz przerwę i dostaniesz trochę jedzenia. Następnie ponownie rozpoczynasz pisanie. Wykonujesz teraz dwie role (pisanie i jedzenie) przez okno czasowe uważane za równoczesne zatrudnienie. Należy podkreślić, że te dwa zadania (pisanie i jedzenie) nadal muszą być ukończone równolegle. Kiedy przedmioty są ukończone jednocześnie, określa się to jako równoległość (wyobraź sobie, że używasz telefonu komórkowego podczas chrupania chipsów). Współbieżność obejmuje interakcję z wieloma rzeczami jednocześnie. Paralelizm (wykonywanie wielu rzeczy jednocześnie) jest podklasą tego (nie musi być wykonywany w tym samym czasie) z pewnym harmonogramem.
Możemy dodać goroutine poprzez zastosowanie słowa kluczowego go do wywołania funkcji. Gdy zastosujemy słowo kluczowe go do wywołania funkcji, ustawimy współbieżność na wykonanie. Ale najpierw określmy efekt zastosowania słowa kluczowego go do wykonania. Rozważmy, że w programie znajdują się dwie goroutines. Tekst "package main import" będzie wpisem programu. W Go, package main import jest deklaratywną deklaracją importu. Główny goroutine (first goroutine) jest implikowany. Kiedy wykonujemy go (f), powstaje drugi goroutine (0). Zazwyczaj Nasze oprogramowanie wykona każde polecenie w funkcji głównej, gdy wykonamy funkcję przed przejściem do następnego wiersza.
Możemy szybko uruchomić procedurę za pomocą goroutine przed przejściem do następnego kroku. W rezultacie dodano metodę scanln; w przeciwnym razie kod zakończyłby się przed pokazaniem wszystkich liczb. Goroutines są proste w tworzeniu i mogą być wykonywane w dużych ilościach. Zauważysz, że gdy ten program jest uruchamiany, goroutines wydają się działać sekwencyjnie, a nie współbieżnie.
Zalety Goroutines nad wątkami
Goroutines kosztują niewiele
Goroutines są mniej kosztowne niż inne procesy. Rozmiar masy wynosi tylko kilka kilobajtów i może się rozszerzać lub kurczyć, aby spełnić wymagania programu, w przeciwieństwie do wątków, których rozmiar stosu musi być zdefiniowany i jest stały.
Wątki są zwielokrotnione Goroutines
Istnieje bardzo niewiele wątków systemu operacyjnego, do których są one multipleksowane. W programie z setkami goroutines może być tylko jeden proces. Reszta goroutines jest przekazywana do nowego procesu systemu operacyjnego. Załóżmy, że jakakolwiek goroutine w tym procesie utknęła, na przykład, gdy szuka interwencji użytkownika. Runtime zarządza każdym z nich, a my, programiści, otrzymujemy przejrzyste API, aby zarządzać jednocześnie, będąc izolowanym od tych subtelnych zawiłości.
Goroutines komunikować się za pomocą kanałów
Goroutines konwersować używając kanałów. Zamierzone, aby zapobiec sytuacjom wyścigu, gdy dzielą odpowiednią pamięć. Kanały można porównać do przepustu, którego goroutines używają do interakcji.
Czym są kanały?
Dwa goroutines mogą oddziaływać ze sobą i koordynować swoje działanie poprzez kanały. Ten program będzie stale wypisywał "ping". Aby oznaczyć postać kanału, przedrostkowi "chan" towarzyszą elementy przekazywane na kanale." W tym przypadku podajemy ciągi znaków. Na kanale wiadomości są wysyłane i odbierane za pomocą operatora. "ping" odnosi się do wysyłania "ping".
Kanał jest używany do utrzymywania dwóch goroutines w synchronizacji. Przed próbą wysłania wiadomości przez kanał, router będzie czekał, aż drukarka będzie gotowa ją przyjąć. Termin na to to inhibicja. Podczas tworzenia kanału, drugi parametr może być użyty dla funkcji make: c:= make (chan int, 1)
Kierunek kanału
Możemy zdefiniować orientację formy kanału i parametryzować go na odbiór lub nadawanie. Na przykład znak metody Pinger można zmienić na:
func pinger(c chan<- string)
C może być wysyłane tylko teraz. Odebranie od c spowoduje błąd kodu. Podobnie możemy zmodyfikować wyjście do:
func printer(c string -chan)
Półkanał nie ma tych ograniczeń. Kanał dwukierunkowy może być dostarczony do procedury, która akceptuje tylko kanały transmit-only lub accept-only, ale nie odwrotnie.
Jak stworzyć goroutine?
Metoda uruchomienia goroutine jest prosta. Zastosuj słowo kluczowe "go" do wywołania funkcji, aby stworzyć goroutine, który będzie wykonywany współbieżnie. Tutaj zajmiemy się stworzeniem goroutine. Załóżmy, że mamy program zawierający dwie funkcje: jedna to funkcja powitalna, a druga to funkcja główna.
Gdy utworzymy nową goroutine, kod powitalny () będzie wykonywany obok funkcji main(). Gdy wykonasz ten program, będziesz zaskoczony. Ten program jedynie pokazuje tekst głównej operacji. Co się stało z pierwszym goroutine lub nowym goroutine, który zainicjowaliśmy? Aby zrozumieć, dlaczego tak się dzieje, musimy najpierw poznać dwie główne cechy goroutine'ów.
- Funkcja goroutine reaguje natychmiast, gdy tworzymy nowy goroutine. Oprócz funkcji, zarządzanie nie polega na goroutine, więc nie czeka na zakończenie jego wykonania. Wykonanie jest przekazywane do następnego bloku kodu po funkcji goroutine. Dlatego też wszelkie podane parametry z goroutine są ignorowane.
- Wszelkie dodatkowe goroutiny powinny działać współbieżnie z głównym goroutinem. Jeśli główny goroutine zawiedzie, program zakończy pracę, a żadne dodatkowe goroutine'y nie będą uruchamiane.
Teraz rozumiesz, dlaczego nasz kod nie zadziałał. Po wywołaniu funkcji go welcome(), kontrola została przekazana do następującej linii kodu, zanim czekano na zakończenie działania goroutine hello, a funkcja main została wyprowadzona. Główny goroutine umarł, ponieważ nie było żadnego skryptu do wykonania, uniemożliwiając uruchomienie goroutine hello.
Wywołaliśmy technikę snu (time.sleep(1 * time.second)), aby wstrzymać goroutine na 1 sekundę. Funkcja do powitania () ma teraz wystarczająco dużo czasu, aby zakończyć, zanim główny goroutine wyjdzie. Ten program początkowo pisze "welcome goroutine", a następnie czeka jedną sekundę przed wydrukowaniem głównej funkcji. Używamy techniki sleep w głównym goroutine, aby wstrzymać go na chwilę, aby pozwolić innym goroutines zakończyć.
Tworzenie wielu Goroutines
Zamierzamy uruchomić kolejny program, aby stworzyć wiele goroutines. Możemy zacząć od utworzenia dwóch goroutines, które będą wykonywać się równolegle. Te dwa goroutiny to numbers goroutines[go numbers()] i alphabet goroutines [go alphabets ()].
Goroutine liczbowy pozostaje przez 250 ms przed wydrukowaniem 1, ponownie odpoczywa przed wydrukowaniem 2, i tak dalej, dopóki nie wyprodukuje 5. Podobnie, alfanumeryczna goroutine wyświetla literę od a do e, a następnie czeka 400 milisekund. Na koniec The primary goroutine tworzy liczby całkowite i znaki alfanumeryczne i wstrzymuje się na whike, a następnie kończy pracę main goroutine.
Najczęstsze błędy w programowaniu współbieżnym
- Brak synchronizacji, gdy jest to wymagane
- Używanie czasu. Sleep do wykonania synchronizacji
- Pozostawienie goroutines dangling wartości kopii typów w standardowym pakiecie sync
- Wywołaj synchronizację
- Waitgroup
- Dodaj metody w niewłaściwych miejscach
- Użyj kanałów jako bliskich kanałów jutra, a nie z ostatniego funkcjonalnego goroutine nadawcy
Podsumowanie
W tym artykule stworzyliśmy program, który wykorzystywał słowo kluczowe go do uruchomienia jednego goroutine i wielu goroutine, które jednocześnie drukowały liczby całkowite. Po uruchomieniu tego programu utworzyliśmy nowy kanał, który następnie wykorzystaliśmy do wytworzenia liczb w jednym goroutinie i przekazania ich do innego goroutinu, aby mogły zostać wyświetlone na ekranie. Jako ostatnią demonstrację sposobu uruchamiania goroutine'ów w celu przyspieszenia działania aplikacji na systemach wielordzeniowych, uruchomiłeś jednocześnie wiele goroutine'ów "drukujących".
Jak wiemy, goroutiny są sposobem na szybsze i wydajniejsze wykonywanie zadań. Jest to jedna z procedur wdrożeniowych oferowanych przez AppMaster w celu poprawy funkcjonalności Twojej aplikacji. Dzięki AppMaster nawet osoby o niewielkiej lub zerowej wiedzy programistycznej mogą wykonać zadania, które byłyby trudne do wykonania poprzez ręczne kodowanie.
AppMaster jest no-code platforma, która jest w stanie tworzyć aplikacje mobilne i webowe oraz backend. Ciekawostką jest fakt, że AppMaster tworzy backend przez Go z prędkością 22 000 linii na sekundę, a Ty masz dostęp do kodu źródłowego.