zamówiony Licznik serwera
powyższy przykład to uporządkowany licznik serwera, który chcemy zbudować. Po kliknięciu przycisku:
- zapytanie asynchroniczne jest wysyłane do serwera
- serwer zwiększa wewnętrzny licznik
- serwer zwraca bieżącą wartość licznika
- klient (nasza strona internetowa) wyświetla licznik w toastie pokazanym powyżej.
ważne jest, aby kolejność numerów była zachowana po otrzymaniu. Jak więc możemy zsynchronizować kolejność żądań? Wiemy, że żądania sieciowe są asynchroniczne. Jest całkowicie możliwe, aby pierwsze żądanie trwało dłużej niż drugie żądanie, lub drugie żądanie trwało dłużej niż trzecie żądanie, i tak dalej. To nieaktualne przybycie wniosków będzie problemem dla naszej aplikacji.
podejście „bez synchronizacji”
co by się stało, gdybyśmy mieli opracować tę aplikację bez konstruktów synchronizacji? Oto przykładowa implementacja symulacji tej aplikacji bez synchronizacji.
serwer jest symulowany za pomocą processCommmand()
, a opóźnienia sieci są symulowane za pomocą serverDelay()
. Ponieważ nie ma mechanizmów synchronizacji, po kliknięciu przycisku „Kliknij mnie”, nowe żądanie jest natychmiast uruchamiane.
jest to wynik tej implementacji.
Uh oh-liczby, zgodnie z oczekiwaniami, pojawiają się nie w porządku, a my nie złożyliśmy wniosku o pokazanie liczb w kolejności.
rozwiązanie problemu z mutex
problem polega na tym, że żądania sieciowe są nie w porządku, ale nasza aplikacja chce, aby były w porządku. Jednym ze sposobów rozwiązania tego problemu jest użycie blokady Mutex, aby umożliwić przetwarzanie tylko jednego żądania na raz, blokując Pozostałe żądania, dopóki nie nadejdzie ich kolej.
oto implementacja z Mutex.
przepływ użycia interfejsu API Mutex jest następujący:
- linia 23: żądanie nabycia
clientLock
jest inicjowane. To żądanie zostanie zablokowane, jeśli ktoś inny już nabył blokadę i jeszcze jej nie wydał - linia 33: blokada klienta jest zwalniana po odpowiedzi serwera i pokazaliśmy toast. Dzięki temu inne zdarzenia klikające przycisk mogą teraz rywalizować o blokadę i inicjować żądanie sieci serwerów!
ten mechanizm blokujący gwarantuje, że tylko jedno zdarzenie przycisku będzie przetwarzane naraz, blokując i kolejkując Pozostałe. Osiągnęliśmy zamierzoną, zamówioną realizację naszego oryginalnego przykładu pokazanego na początku!
ograniczenie liczby widocznych toastów
co jeśli nie podoba Ci się, że kilka toastów może zalać ekran na raz? Możemy rozszerzyć naszą logikę, aby ograniczyć liczbę toastów wyświetlanych naraz. Nasz konstruktor synchronizacji byłby semaforem!
pomyśl o Sempahorze jak o Mutexie, ale może on zezwalać na wykonywanie wielu asynchronicznych żądań naraz. Możesz również skonfigurować maksymalną liczbę!
używając Mutex i semafora, udało mi się ograniczyć liczbę toastów na ekranie do 2 naraz.
a oto kod powiązany z powyższym przykładem
linia 6
struktura Sempahore jest inicjowana wartością 2, która określa, że tylko maksymalnie 2 toasty mogą być wyświetlone w czasie.
linia 26-31
nasza logika semaforów pomaga nam, gdy chcemy wyświetlić Toast. Próbujemy zdobyć Sempahore. Jeśli nam się udało, to tworzymy obiekt Toast, a następnie przekazujemy releaseSemaphore()
do funkcji completeCallback
Toast. Ten telefon jest wywoływany, gdy toast jest odrzucony.