Az olvasás-írás zárak fogalma egyszerű: lehetővé teszi, hogy több szál egyszerre szerezzen olvasási zárat, de csak egy szál képes egyszerre írózárokat szerezni, így ezt megosztott-exkluzív zárnak is nevezik. C#-ban ajánlott a ReaderWriterLockSlim osztályt használni az olvasás/írás funkció teljesítéséhez. Bizonyos esetekben az objektumhoz érkező olvasások száma sokkal nagyobb, mint a módosítások száma, és ha egyszerűen zárolással zárják, az befolyásolja az olvasás hatékonyságát. Ha read-write zárat használnak, több szál egyszerre olvashatja az objektumot, és csak akkor blokkolódik, ha az objektumot a write-lock foglalja el. Egyszerűen fogalmazva, amikor egy szál olvasási módba lép, más szálak is olvasási módba léphetnek, feltéve, hogy egy szál akkor szeretne írási módba lépni, akkor blokkolni kell. Amíg el nem lép az olvasási mód. Hasonlóképpen, ha egy szál írási módba kapcsol, a többi szál is blokkolódik, akár írni, akár olvasni akarnak. Kétféleképpen lehet írás/olvasási módba lépni: Az EnterReadLock megpróbál belépni az írásmód zárolási állapotába. TryEnterReadLock(Int32) megpróbál belépni az olvasási mód zárolási állapotába, ahol egy egész szám időkérés opciója van. Az EnterWriteLock megpróbálja belépni a Write Mode Lock állapotba. A TryEnterWriteLock(Int32) megpróbál belépni az írásmód zárolási állapotába, és kiválasztható az időtúlzási idő. Kétféleképpen lehet kilépni az írás/olvasási módból: Az ExitReadLock csökkenti az olvasási mód rekurzív számát, és akkor lép ki az olvasási módból, ha a kapott szám 0 (nulla). Az ExitWriteLock csökkenti az írási minta rekurzív számát, és akkor lép ki az írásmódból, amikor a szám 0 (nulla). Íme, hogyan lehet használni:
Látható, hogy a 3-as és 4-es szál egyszerre léphet olvasási módba, míg az 5-ös szál 5 másodperc után (azaz miután a 3-as és 4-es szál kilép az olvasási zárból) írási módba. Módosítsuk a fenti kódot, először nyiss ki 2 szálat írásmódban, majd nyitj szálakat olvasási módban, a kód a következő:
Az eredmények a következők:
Ahogy látod, a 3-as szál és a 4-es szál is írási módba lép, de a 3-as szál foglalja el először az írási zárat, így a 4-es szálnak 10 másodpercet kell várnia, mielőtt belép. Az 5. és 6. szálnak el kell foglalniuk az olvasási zárat, ezért várd meg, amíg a 4-es szál kilép az írási zárból, mielőtt folytatnánk. A TryEnterReadLock és a TryEnterWriteLock beállíthat időtúllépést, amikor erre a mondatra fut, a szál itt blokkolódik, ha a zár éppen foglalható, akkor visszatér true értéket, ha az időkérés még nem foglalta el a zárat, akkor visszaadja a false-t, feladja a zár elfoglalását, és folytatja a következő kód közvetlen futtatását. EnterUpgradeableReadLock A ReaderWriterLockSlim osztály frissíthető olvasási módot biztosít, amely eltér az olvasási módtól abban is, hogy az EnterWriteLock vagy a TryEnterWriteLock metódusok hívásával is frissíthető írásmódra. Mert egyszerre csak egy thread lehet fejleszthető módban. Az a szál, amely fejleszthető módba lép, nem befolyásolja a szálat olvasási módban, vagyis amikor egy szál frissíthető módba lép, bármennyi szál egyszerre léphet olvasási módba blokkolás nélkül. Ha több szál már vár a write lock megszerzésére, az EnterUpgradeableReadLock futtatása blokkol, amíg ezek a szálak el nem érnek idővel vagy ki nem lépnek az írási zárból. Az alábbi kód bemutatja, hogyan lehet frissíteni írási zárra fejleszthető olvasási módban.
Az olvasási/írási zárak teljesítményre gyakorolt hatása nyilvánvaló. A következő tesztkód:
A fenti kód 500 feladat működését szimulálja, amelyek mindegyike egy szál pool szálat foglal el, ebből 20 írási szál, 480 olvasási szál szimulált. Az adatok olvasása 10 ms, az írás pedig 100 ms a zárolási módszer és a ReaderWriterLockSlim módszer teszteléséhez. A ReaderWriterLockSlim esetében becslés elképzelhető, feltételezve, hogy egyszerre 480 szálat olvasnak, akkor 10 ms elfogyaszt, 20 írási művelet 2000 ms-t foglal el, így az idő 2010 ms, a hagyományos zárolási módszer esetén, mivel mindegyik exkluzív, így 480 olvasási művelet 4800 ms + 20 írási művelet 2000ms = 6800ms. Az eredmények észrevehető teljesítményjavulást mutattak.
|