Programowanie synchroniczne/asynchroniczne
Jeśli dzwoniący wysyła wiadomość do odbiorcy i czeka na odpowiedź, czy może zrobić coś innego? Mówię dzwoniącego/odbiorcę zamiast serwera/klienta, ponieważ te połączenia zdarzają się wszędzie. Z założenia, kiedy po raz pierwszy zbudowaliśmy komputery, wszystko było synchroniczne. Można to postrzegać jako falę sinusoidalną, w której dzwoniący i serwer są zsynchronizowani lub mają ten sam rytm. Asynchroniczne oznacza, że nie są zsynchronizowane.
Synchroniczne wejście/wyjście
Osoba dzwoniąca wysyła żądanie do odbiorcy, a następnie je blokuje. Dzieje się tak, gdy dzwoniący jest blokowany, nic nie robi, a zatem całkowita strata czasu. W dawnych czasach procesor usuwał proces z procesora, myśląc, że jest po prostu zablokowany, i dodawał nowy proces, który nie jest blokowany (przełączanie kontekstu). W międzyczasie dzwoniący nie może wykonać. Wreszcie, gdy odbiornik odpowiada, system operacyjny może skierować proces z powrotem do procesora. Dlatego dzwoniący zostaje odblokowany. To pokazuje, jak klient i serwer są całkowicie zsynchronizowane.
Przykład synchronicznego wejścia/wyjścia systemu operacyjnego:
1. Program prosi procesor o odczytanie pliku z dysku.
2. Główny wątek programu zostaje zdjęty z procesora.
3. Odczyt zostanie zakończony, a program wznowi działanie.
// A simple Js example
// Program starts
// Programs uses CPU to execute work.
SampleFunction();
// Program reads from the disk
// Program can't do anything until file loads
readfile("SyncExample.dat")
// Program resumes
Mówiąc konkretnie z punktu widzenia NodeJs, używa epoll w Linuksie, aw przypadku Windows używa stosu uzupełniania. Inną rzeczą, którą robi nodeJs, jest uruchamianie nowego wątku, który blokuje się na wypadek, gdyby coś wymagało wykonania operacji blokowania. Domyślnie Nodejs ma 4 wątki robocze w bibliotece libuv , których używa do operacji I/O, ale jest to konfigurowalne.
Przykład asynchronicznego wywołania systemu operacyjnego (NodeJS)
a) Program uruchamia wątek wtórny
b) Wątek wtórny odczytuje dane z dysku. Oczywiście system operacyjny usuwa z bieżącego procesora
c) program główny nadal działa i jest wykonywany.
d) Wątek kończy i wywołuje główny wątek.
// A simple Javascript example
// Program starts
// Programs uses CPU to execute work.
SampleFunction();
// Program reads from the disk
// Program hapilly moves on to the samplefunction2
readfile("SyncExample.dat", onReadFinish(console.log))
//file is not probably read yet
SampleFunction2();
//onReadFinish function called
// executing it
Teraz omówimy sprawy wyłącznie z punktu widzenia klienta i serwera (zaplecza).
Tak więc synchroniczność może być również znana jako właściwość klienta, w której może czekać lub przejść dalej. Obecnie żaden klient nie jest synchroniczny, a większość bibliotek jest asynchroniczna. Głównie klient wysyła żądanie i otrzymuje odpowiedź, a niektóre wywołania zwrotne są wywoływane za każdym razem, gdy odpowiedź jest wykonywana. Tak więc konkretnie w Node.js istnieje główna pętla zdarzeń, która sprawdza odpowiedź.
Może to być mylące, ponieważ zawsze było dla mnie, gdy ktoś wyjaśniał to za pomocą tego pięknego przykładu z życia wziętego, że synchroniczne jest jak zadawanie pytania na spotkaniu, na którym spotkanie zostanie przeniesione, jeśli prezenter odpowie. Asynchroniczne jest jak zadawanie pytań w wiadomości e-mail, na które można odpowiedzieć, gdy tylko odbiorca znajdzie czas.
Asynchroniczne przetwarzanie zaplecza
Będąc inżynierem backendu, byłoby niesprawiedliwe, gdybym nie mówił o asynchronizacji backendu. W wielu kodach/repozytoriach klient jest przede wszystkim asynchroniczny, ale backend wciąż każe mu czekać. Kiedy więc klient prosi o przekazanie pewnych danych, powiedzmy o wywołanie bazy danych, wiele razy jest proszony o zaczekanie na odpowiedź z zaplecza, które zwraca odpowiedź o statusie 200 po zatwierdzeniu. Teraz, jeśli przeniesiemy obiektyw do backendu, frontend jest asynchroniczny, ale backend jest nadal synchroniczny. Jak więc zwrócić natychmiastową odpowiedź?
Jednym z rozwiązań jest użycie tej pięknej struktury danych, zwanej kolejką. Jeśli klient wyśle żądanie, nie obiecujemy natychmiastowego wykonania, ale umieścimy je w kolejce. Powodem tego jest to, że backend może realizować poprzednie żądania, a klient nie jest już blokowany; możemy wysłać odpowiedź, że ustawiliśmy żądanie w kolejce, a oto obietnica/JobID. Aby uzyskać więcej informacji, możesz przeczytać o kolejkach komunikatów .
Oprócz tego istnieją bardzo popularne rozwiązania, w zależności od przypadku użycia.
Rzeczywisty przykład obciążenia asynchronicznego:
a) Zatwierdzenia asynchroniczne w Postgres ↗ .
b) Asynchroniczne operacje we/wy w systemie Linux (io-uring).
c) Asynchroniczne operacje wejścia/wyjścia fsync (fs-cache): Ilekroć zapisujemy coś do dowolnego pliku, nie jest to bezpośrednio zapisywane na dysku, ale w pamięci podręcznej systemu plików. W systemie operacyjnym znajduje się pamięć podręczna, a zapisy trafiają na strony. Następnie system operacyjny opróżnia wszystkie strony za jednym razem.
Całość możemy podsumować w następujący sposób:
a) Podejście do programowania synchronicznego polega na wykonywaniu zadań sekwencyjnie. Każde zadanie jest wykonywane po odczekaniu na zakończenie poprzedniego zadania.
b) Kiedy zadanie jest uruchamiane w modelu programowania asynchronicznego, możemy przejść do kolejnego bez czekania na zakończenie poprzedniego.
Dziękuje za przeczytanie; Mam nadzieję, że to było pomocne.
W przypadku jakichkolwiek dalszych wątpliwości, skontaktuj się z nami przez LinkedIn / Instagram .

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































