Konseptet med lese-skrive-låser er enkelt, og lar flere tråder skaffe leselåser samtidig, men bare én tråd får tilgang til skrivelåser samtidig, så det kalles også delte-eksklusive låser. I C# anbefales det å bruke ReaderWriterLockSlim-klassen for å fullføre lese/skrive-låsefunksjonen. I noen tilfeller er antall lesinger til et objekt mye større enn antall endringer, og hvis det bare låses ved å låse, vil det påvirke effektiviteten av lesingen. Hvis en lese-skrive-lås brukes, kan flere tråder lese objektet samtidig, og det vil bare bli blokkert når objektet er okkupert av skrive-låsen. Enkelt sagt, når en tråd går inn i lesemodus, kan andre tråder fortsatt gå inn i lesemodus, forutsatt at en tråd ønsker å gå inn i skrivemodus på dette tidspunktet, må den blokkeres. inntil lesemodus avsluttes. På samme måte, hvis en tråd går inn i skrivemodus, vil de andre trådene bli blokkert enten de vil skrive eller lese. Det finnes to måter å gå inn i skrive-/lesemodus på: EnterReadLock forsøker å gå inn i skrivemodus-låsetilstanden. TryEnterReadLock(Int32) forsøker å gå inn i låsetilstanden i lesemodus, med mulighet til å velge en heltalls-timeout. EnterWriteLock forsøker å gå inn i Write Mode Lock-tilstanden. TryEnterWriteLock(Int32) forsøker å gå inn i skrivemodus-låsetilstanden, og timeout-tiden kan velges. Det finnes to måter å avslutte skrive-/lesemodus på: ExitReadLock reduserer den rekursive tellingen i lesemodusen og avslutter lesemodusen når den resulterende tellingen er 0 (null). ExitWriteLock reduserer den rekursive tellingen av skrivemønsteret og forlater skrivemodus når den resulterende tellingen er 0 (null). Slik bruker du den:
Du kan se at tråd 3 og tråd 4 kan gå inn i lesemodus samtidig, mens tråd 5 kan gå inn i skrivemodus etter 5 sekunder (det vil si etter at tråd 3 og 4 har gått ut av leselåsen). Endre koden ovenfor, først åpne 2 tråder i skrivemodus, og deretter åpne tråder i lesemodus, koden er som følger:
Resultatene er som følger:
Som du ser, går både tråd 3 og tråd 4 inn i skrivemodus, men tråd 3 opptar skrivelåsen først, så tråd 4 må vente 10 sekunder før den går inn. Trådene 5 og 6 må være i leselåsen, så vent til tråd 4 forlater skrivelåsen før du fortsetter. TryEnterReadLock og TryEnterWriteLock kan sette en timeout, når de kjører til denne setningen, vil tråden blokkere her, hvis låsen kan opptas nå, returnere true, hvis timeout-tiden ennå ikke har okkupert låsen, deretter returnere false (false up), gi opp okkupasjonen av låsen, og fortsette å kjøre følgende kode direkte. EnterOppgraderbarLeLås ReaderWriterLockSlim-klassen tilbyr en oppgraderbar lesemodus, som skiller seg fra lesemodus ved at den også kan oppgraderes til skrivemodus ved å kalle metodene EnterWriteLock eller TryEnterWriteLock. Fordi bare én tråd kan være i oppgraderbar modus om gangen. En tråd som går inn i oppgraderbar modus vil ikke påvirke tråden i lesemodus, det vil si at når en tråd går inn i oppgraderbar modus, kan et hvilket som helst antall tråder gå inn i lesemodus samtidig uten blokkering. Hvis flere tråder allerede venter på å få en skrivelås, vil kjøring av EnterUpgradeableReadLock blokkere til disse trådene går ut eller de avslutter skrivelåsen. Følgende kode viser hvordan man oppgraderer til en skrivelås i oppgraderbar lesemodus.
Effekten av lese-/skrivelåser på ytelsen er åpenbar. Følgende testkode:
Koden ovenfor simulerer driften av 500 oppgaver, hvor hver opptar en trådpooltråd, hvorav 20 er skrivetråder og 480 lesetråder simuleres. Det tar 10 ms å lese data og 100 ms å skrive for å teste låsemetoden og ReaderWriterLockSlim-metoden henholdsvis. Et estimat kan gjøres for ReaderWriterLockSlim, forutsatt at 480 tråder leses samtidig, deretter bruker det 10 ms, 20 skriveoperasjoner opptar 2000 ms, så tiden som brukes er 2010 ms, og for den vanlige låsemetoden, fordi de alle er eksklusive, opptar 480 leseoperasjoner 4800 ms + 20 skriveoperasjoner 2000 ms = 6800 ms. Resultatene viste en merkbar ytelsesforbedring.
|