Programiranje

Moja dva centa na SpinLock v .Net

Predstavljajte si situacijo, v kateri nit poskuša pridobiti dostop do vira v skupni rabi, vendar je vir že zaklenjen, zato mora nit počakati, dokler se ključavnica ne sprosti. Tukaj pride v poštev sinhronizacija niti. Sinhronizacija niti se uporablja za preprečevanje hkratnega dostopa več niti do vira v skupni rabi. Microsoft .Net Framework zagotavlja podporo za vrsto sinhronizacijskih primitivov, ki se lahko uporabljajo za nadzor vedenja niti in izogibanje dirkalnim pogojem. Mutex in Spinlock sta dva priljubljena sinhronizacijska mehanizma, ki se uporabljata za sinhronizacijo dostopa do skupnega vira.

SpinLock je alternativa blokiranju sinhronizacije. SpinLock (znan tudi kot "Zasedeno čakanje") je mehanizem, s katerim lahko nit poskuša pridobiti zaklepanje v zanki, dokler ne dobi dostopa do vira. Upoštevajte, da lahko SpinLock deluje hitreje v primerjavi z Mutexom, saj je preklop konteksta zmanjšan. Vendar bi morali uporabljati SpinLocks le, če naj bi kritični odsek opravil minimalno količino dela, tj. SpinLock je zadržan zelo kratko. V simetričnih večprocesorskih sistemih so ponavadi prednostni SpinLocks, ki nenehno anketirajo glede razpoložljivosti vira namesto kontekstnih stikal.

Kaj je SpinLock in zakaj je potreben?

SpinLock opravlja zasedeno čakanje in lahko ponudi boljšo zmogljivost, če se uporablja v večjedrnih sistemih, zlasti kadar je poceni čakanje v zanki in združevanje vira, namesto da bi ga blokirali. To je še posebej koristno, če so časi zaklepanja kratki. Z drugimi besedami, SpinLock lahko izkoristite v večjedrnih sistemih, da zmanjšate režijske stroške, povezane s preklapljanjem konteksta, če je čas, porabljen znotraj kritičnega odseka, majhen. Kritični odsek je lahko opredeljen kot podatkovna struktura ali vir, ki si ga deli več niti, vendar ima lahko ena in samo ena nit dostop do njega v danem trenutku.

Upoštevati je treba, da bi bilo daljše držanje SpinLocka preprosto zapravljanje virov sistema in škodljivo za delovanje aplikacije. V bistvu, če pričakujete, da bo blokiranje dolgo trajalo, se SpinLock nikoli ne sme uporabljati - SpinLock uporabljajte samo, ko je čas zaklepanja razmeroma majhen.

SpinLock se običajno uporablja pri delu s prekinitvami za zasedeno čakanje znotraj zanke, dokler vir ni na voljo. SpinLock ne povzroči, da se nit prepreči, temveč se še naprej vrti, dokler se ne sprosti zaklepanje vira.

Programiranje SpinLock-a v .Net

Upoštevajte, da je SpinLock definiran kot struktura v .Net, tj. Je določen kot vrsta vrednosti zaradi razlogov uspešnosti. Torej, če prenašate primerek SpinLock, ga morate posredovati po sklicu in ne po vrednosti. V tem poglavju bomo raziskali, kako lahko programiramo SpinLock v .Net. Če želite implementirati SpinLock v .Net, morate izkoristiti razred SpinLock, ki je na voljo v imenskem prostoru System.Threading.

Naslednji seznam kod prikazuje, kako lahko uporabljate SpinLock v .Net.

SpinLock spinLock = nov SpinLock (resnično);

bool isLocked = false;

poskusite

{

spinLock.Enter (ref isLocked);

// Tukaj napišite svojo običajno kodo

}

končno

{

če (isLocked)

spinLock.Exit ();

}

SpinWait

Upoštevajte, da je tako kot SpinLock tudi SpinWait struktura in ne razred. Podobno kot SpinLock lahko tudi s SpinWait zapišete sinhronizacijsko kodo brez zaklepanja, ki se lahko "zavrti" in ne blokira. SpinWait lahko uporabite za zmanjšanje porabe virov z izvajanjem intenzivnega centrifugiranja procesorja za 10 ponovitev, ki bo zagotovila nadzor s klicem Thread.Yield in Thread.Sleep. Z drugimi besedami, SpinWait lahko uporabimo za omejevanje CPU intenzivnega predenja na določeno število ponovitev. MSDN navaja: "System.Threading.SpinWait je lahka vrsta sinhronizacije, ki jo lahko uporabite v nizkorazrednih scenarijih, da se izognete dragim stikalom konteksta in prehodom jedra, ki so potrebni za dogodke v jedru."

Če želite v svoji kodi uporabiti SpinWait, lahko izkoristite statično metodo SpinUntil () strukture SpinWait ali pa izkoristite nestično metodo SpinOnce (). Naslednji delček kode prikazuje, kako je mogoče uporabiti SpinWait.

SpinWait spinWait = novo SpinWait ();

bool shouldSpin;

medtem ko (! shouldSpin)

{

Thread.MemoryBarrier (); spinWait.SpinOnce ();

}

$config[zx-auto] not found$config[zx-overlay] not found