Koncept lockov na čítanie a zápis je jednoduchý, umožňuje viacerým vláknam získať read locky súčasne, ale len jedno vlákno môže súčasne získať zápisové zámky, preto sa nazýva aj zdieľané exkluzívne zámky. V C# sa odporúča použiť triedu ReaderWriterLockSlim na dokončenie funkcie uzamknutia čítania/zápisu. V niektorých prípadoch je počet čítaní objektu oveľa väčší ako počet modifikácií, a ak je objekt jednoducho uzamknutý, ovplyvní to efektivitu čítania. Ak sa použije zámok čítania a zápisu, viaceré vlákna môžu objekt čítať súčasne a bude zablokovaný len vtedy, keď je objekt obsadený zápis-zámokom. Jednoducho povedané, keď vlákno vstúpi do režimu čítania, ostatné vlákna môžu stále prejsť do režimu čítania, za predpokladu, že vlákno chce v tomto čase prejsť do režimu zápisu, musí byť zablokované. Až kým režim čítania neukončí. Podobne, ak vlákno prejde do režimu zápisu, ostatné vlákna budú zablokované, či už chcú písať alebo čítať. Existujú 2 spôsoby, ako vstúpiť do režimu zápisu/čítania: EnterReadLock sa pokúša vstúpiť do stavu uzamknutia v režime zápisu. TryEnterReadLock(Int32) sa pokúša vstúpiť do stavu uzamknutia v režime čítania s možnosťou vybrať celočíselný časový limit. EnterWriteLock sa pokúša vstúpiť do stavu Write Mode Lock. TryEnterWriteLock(Int32) sa pokúša vstúpiť do stavu uzamknutia režimu zápisu a je možné zvoliť čas vypršania času. Existujú 2 spôsoby, ako opustiť režim zápisu/čítania: ExitReadLock znižuje rekurzívny počet čítacieho režimu a ukončí čítací režim, keď je výsledný počet 0 (nula). ExitWriteLock znižuje rekurzívny počet zápisového vzoru a ukončí zápisový režim, keď je výsledný počet 0 (nula). Tu je návod, ako ho používať:
Vidíte, že vlákno 3 a vlákno 4 môžu prejsť do režimu čítania súčasne, zatiaľ čo vlákno 5 môže prejsť do režimu zápisu po 5 sekundách (teda po tom, čo vlákna 3 a 4 opustia zámok čítania). Upravte vyššie uvedený kód, najprv otvorte 2 vlákna v režime zápisu a potom otvorte vlákna v režime čítania, kód je nasledovný:
Výsledky sú nasledovné:
Ako vidíte, vlákno 3 aj vlákno 4 vstupujú do režimu zápisu, ale vlákno 3 najprv obsadí write lock, takže vlákno 4 musí počkať 10 sekúnd pred vstupom. Vlákna 5 a 6 musia obsadiť zámok čítania, takže počkajte, kým vlákno 4 opustí zápisový zámok, než pokračujete. TryEnterReadLock a TryEnterWriteLock môžu nastaviť časový limit, pri spustení tejto vety vlákno zablokuje tu, ak je zámok v tomto čase obsadený, potom vráť true, ak časový limit ešte neobsadil zámok, potom vráť nepravdivo, vzdať sa obsadenia zámku a pokračovať v priamom vykonávaní nasledujúceho kódu. Prichádza UpgradeableReadLock Trieda ReaderWriterLockSlim poskytuje upgradovateľný režim čítania, ktorý sa líši od režimu čítania tým, že ho je možné tiež upgradovať do režimu zápisu volaním metód EnterWriteLock alebo TryEnterWriteLock. Pretože len jedno vlákno môže byť v režime upgradovania naraz. Vlákno, ktoré vstúpi do režimu upgraduable, neovplyvní vlákno v režime čítania, teda keď vlákno vstúpi do upgradovateľného režimu, ľubovoľný počet vlákien môže naraz prejsť do režimu čítania bez blokovania. Ak už viacero vlákien čaká na získanie zápisového zámku, spustenie EnterUpgradeableReadLock zablokuje, kým tieto vlákna nevypršia alebo neukončia zápisový zámok. Nasledujúci kód ukazuje, ako upgradovať na zápisový zámok v upgradovateľnom režime čítania.
Vplyv zámkov čítania/zápisu na výkon je zrejmý. Nasledujúci testovací kód:
Vyššie uvedený kód simuluje prevádzku 500 úloh, z ktorých každá zaberá vlákno vlákna, z ktorých 20 sú vlákna na zápis a 480 na čítanie je simulovaných. Na načítanie dát trvá 10 ms a na zápis 100 ms, aby sa otestovala metóda zámku a metóda ReaderWriterLockSlim. Pre ReaderWriterLockSlim je možné odhadnúť, že za predpokladu, že 480 vlákien sa číta súčasne, potom spotrebuje 10 ms, 20 zápisových operácií zaberá 2000ms, takže čas spotrebovaný je 2010ms, a pre bežnú metódu zámku, pretože sú všetky exkluzívne, takže 480 čítacích operácií zaberá 4800ms + 20 zápisových operácií 2000ms = 6800ms. Výsledky ukázali výrazné zlepšenie výkonu.
|