contor Server comandat
exemplul de mai sus este un contor de server ordonat pe care dorim să-l construim. Când faceți clic pe buton:
- o cerere asincronă este trimisă la un server
- serverul incrementează un contor intern
- serverul returnează valoarea contorului curent
- clientul (pagina noastră web) afișează contorul într-un Toast prezentat mai sus.
este important ca ordinea numerelor să fie păstrată atunci când este primită. Deci, cum putem sincroniza ordinea cererilor? Știm că cererile de rețea sunt asincrone. Este total posibil ca prima cerere să dureze mai mult decât a doua cerere sau a doua cerere să dureze mai mult decât a treia cerere și așa mai departe. Această sosire în afara comenzii a cererilor va fi o problemă pentru aplicația noastră.
abordarea ‘fără sincronizare’
ce s-ar întâmpla dacă am dezvolta această aplicație fără construcții de sincronizare? Aici este o implementare eșantion de o simulare a acestei aplicații cu nici o sincronizare.
serverul este simulat cu processCommmand()
, iar întârzierile de rețea sunt simulate cu serverDelay()
. Deoarece nu există mecanisme de sincronizare, odată ce se face clic pe butonul „Faceți clic pe mine”, o nouă solicitare este declanșată imediat.
acesta este rezultatul acestei implementări.
uh oh — numerele, așa cum era de așteptat, apar în afara ordinii și nu am reușit să facem aplicația noastră pentru a afișa numerele în ordine.
depășirea problemei out-of-order cu Mutex
problema este că cererile de rețea sunt în ordine, dar aplicația noastră vrea ca acestea să fie în ordine. O modalitate de a rezolva acest lucru este de a utiliza o blocare Mutex pentru a permite procesarea unei singure cereri la un moment dat, blocând celelalte cereri până când este rândul lor.
aici este implementarea cu Mutex.
fluxul de utilizare API Mutex este următorul:
- linia 23: este inițiată o cerere de achiziționare a
clientLock
. Această solicitare se va bloca dacă altcineva a achiziționat deja blocarea și nu a lansat-o încă - linia 33: blocarea clientului este eliberată după ce serverul a răspuns și am arătat toastul. Acest lucru permite altor evenimente de clic pe buton să concureze acum pentru blocare și să inițieze cererea lor de rețea de server!
acest mecanism de blocare garantează că un singur eveniment de buton va fi procesat la un moment dat, blocând și așteptând celelalte. Am realizat acum implementarea ordonată intenționată a exemplului nostru original prezentat la început!
limitarea numărului de toasturi vizibile
ce se întâmplă dacă nu vă place că mai multe toasturi pot inunda ecranul la un moment dat? Ne putem extinde logica pentru a limita numărul de toasturi afișate la un moment dat. Construcția noastră de sincronizare ar fi un semafor!
gândiți-vă la un Sempahore ca un Mutex, dar poate permite mai multor cereri asincrone să execute o bucată de cod la un moment dat. Puteți configura numărul maxim, de asemenea!
folosind un Mutex și un semafor, am reușit să limitez numărul de toasturi de pe ecran la 2 la un moment dat.
și aici este codul asociat cu exemplul de mai sus
linia 6
structura Sempahore este inițializată cu valoarea 2, care specifică faptul că numai un maxim de 2 toasturi pot fi afișate un timp.
linia 26-31
logica noastră semafor vine să ne ajute atunci când vrem să afișăm toastul. Încercăm să dobândim Sempahore. Dacă am fost reușiți, atunci creăm obiectul Toast și apoi trecem releaseSemaphore()
la funcția completeCallback
a toastului. Acest apel invers este numit atunci când toastul este respins.