Programmering

Mine to øre på SpinLock i .Net

Tenk deg en situasjon der en tråd prøver å skaffe seg tilgang til en delt ressurs, men ressursen allerede er låst, så tråden må vente til låsen frigjøres. Her kommer trådssynkronisering inn i bildet. Trådesynkronisering brukes til å forhindre at flere tråder får tilgang til en delt ressurs samtidig. Microsoft .Net Framework gir støtte for en rekke synkroniseringsprimitiver som kan brukes til å kontrollere trådadferd og unngå løpsforhold. Mutex og Spinlock er to populære synkroniseringsmekanismer som brukes til å synkronisere tilgang til en delt ressurs.

En SpinLock er et alternativ til å blokkere synkronisering. SpinLock (også kjent som "Busy Waiting") er en mekanisme som kan brukes til å gjøre en tråd som prøver å skaffe seg en lås, vente i en løkke til den kan få tilgang til ressursen. Merk at SpinLock kan prestere raskere sammenlignet med Mutex siden kontekstbytte er redusert. Du bør imidlertid bare bruke SpinLocks hvis den kritiske delen skal utføre et minimum av arbeid, dvs. SpinLock holdes i en veldig kort periode. SpinLocks foretrekkes vanligvis i symmetriske flerprosessorsystemer enn kontinuerlig avstemning for tilgjengeligheten av en ressurs i stedet for kontekstbrytere.

Hva er SpinLock og hvorfor er det nødvendig?

SpinLock utfører opptatt venter og kan tilby bedre ytelse når den brukes i flerkjernesystemer, spesielt når det er billig å vente i en løkke og samle en ressurs i stedet for å blokkere den. Dette er spesielt nyttig når låsetiden har kort varighet. Med andre ord, du kan dra nytte av SpinLock i flerkjernesystemer for å redusere overhead involvert i kontekstbytte hvis tiden som skal tilbringes inne i den kritiske delen er liten. En kritisk seksjon kan defineres som en datastruktur eller en ressurs som deles av flere tråder, men en og samme tråd kan ha tilgang til den på et gitt tidspunkt.

Det skal bemerkes at å holde SpinLock i lengre tid bare ville være bortkastet systemets ressurser og skadelig for applikasjonens ytelse. I hovedsak, hvis du forventer at blokkeringen har en betydelig varighet, bør SpinLock aldri brukes - bruk SpinLock bare når låsetiden har en ganske liten varighet.

SpinLock brukes vanligvis når du arbeider med avbrudd for å utføre opptatt venter i en løkke til ressursen blir gjort tilgjengelig. SpinLock får ikke tråden til å bli forhindret, men snarere snurrer den til låsen på ressursen frigjøres.

Programmering av SpinLock i .Net

Merk at en SpinLock er definert som en struktur i .Net, dvs. den er definert som en verditype av ytelsesgrunner. Derfor, hvis du passerer rundt en SpinLock-forekomst, bør du sende den med referanse og ikke etter verdi. I denne delen vil vi undersøke hvordan vi kan programmere SpinLock i .Net. For å implementere SpinLock i .Net, må du dra nytte av SpinLock-klassen som er tilgjengelig i System.Threading-navneområdet.

Følgende kodeliste viser hvordan du kan bruke SpinLock i .Net.

SpinLock spinLock = ny SpinLock (true);

bool isLocked = false;

prøve

{

spinLock.Enter (ref isLocked);

// Skriv din vanlige kode her

}

endelig

{

hvis (erLåst)

spinLock.Exit ();

}

SpinWait

Merk at i likhet med SpinLock er SpinWait også en struktur og ikke en klasse. I likhet med SpinLock kan du bruke SpinWait til å skrive låsefri synkroniseringskode som kan "spinne" i stedet for å blokkere. SpinWait kan brukes til å redusere ressursforbruket ved å utføre CPU-intensiv spinning i 10 iterasjoner etter at det vil gi kontrollen ved å ringe Thread.Yield og Thread.Sleep. Med andre ord kan SpinWait brukes til å begrense CPU-intensiv spinning til et fast antall iterasjoner. MSDN sier: "System.Threading.SpinWait er en lett synkroniseringstype som du kan bruke i scenarier på lavt nivå for å unngå dyre kontekstbrytere og kjerneoverganger som kreves for kernehendelser."

For å bruke SpinWait i koden din, kan du enten utnytte den statiske metoden SpinUntil () i SpinWait-strukturen, eller dra nytte av den ikke-statiske metoden SpinOnce (). Følgende kodebit illustrerer hvordan SpinWait kan brukes.

SpinWait spinWait = ny SpinWait ();

bool shouldSpin;

mens (! shouldSpin)

{

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

}

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