Írás-olvasás zár

Az olvasási-írási zár egy szinkronizációs mechanizmus, amely lehetővé teszi egyes megosztott adatok egyidejű általános olvasását vagy azok kizárólagos módosítását, így elhatárolja egymás között az olvasási és írási zárakat [1] . A mechanizmust a klasszikus olvasó-író probléma megoldására tervezték , amelyben bizonyos objektumokat párhuzamos feladatok egyszerre olvasnak és írnak [2] .

A mutexekkel ellentétben az olvasási-írási zárak külön figyelembe veszik az olvasási és külön írási adatokat, lehetővé téve az adatokhoz való hozzáférést, ha azok abban az időben nem változnak. A mutexek csak kizárólagos hozzáférést tesznek lehetővé az adatokhoz [1] . Vannak azonban megosztott mutexek, amelyek az exkluzív záron kívül egy megosztott zárat is biztosítanak, amely lehetővé teszi a mutex megosztott tulajdonjogát, ha nincs kizárólagos tulajdonos [3] . Lényegében a megosztott mutexek olvasási-írási zárak, de mutexeknek nevezik őket.

Az olvasási-írási zárak általában ugyanazt a problémát oldják meg, mint a mutexek, helyettesíthetők velük, de az olvasási-írási zárszerkezet megjelenésének oka a kölcsönös kizárás hatékonyságának növelése külön olvasással és írással [ 4] . Az olvasási-írási zárolást előnyben részesítik a mutexekkel szemben olyan esetekben, amikor az adatokhoz sokkal gyakrabban hozzáférnek, mint írnak. Ebben az esetben az olvasási feladatok legtöbbször nem blokkolnak, csak néha blokkolnak, amikor az objektum megváltozik. Az írási és olvasási feladatok között gyakran az írási feladatok adnak elsőbbséget, hogy elkerüljük az írási feladatok erőforrás-éhezését [1] .

Az olvasó-író probléma

Az olvasók és írók problémája minden olyan helyzetben felmerül, amikor egy adatstruktúra, fájlrendszer vagy adatbázis egyidejű olvasását és módosítását párhuzamos feladatok teszik szükségessé. A változtathatatlan adatok olvasása egyszerre több feladattal is elvégezhető, azonban ha ekkor történik adatváltozás, akkor azok párhuzamos olvasása részben módosult adatokhoz, azaz sérült adatokhoz vezethet [2] .

A probléma megoldása aszimmetrikus, és magában foglalja a zár felosztását olvasásra és írásra. Az adatok módosítása csak exkluzív, azaz egyszerre csak egy feladat szerezhet írási zárolást, hacsak nincs olvasási zár. Az adatok olvasása sok feladattal elvégezhető, így tetszőleges számú feladat szerezhet egyidejűleg olvasási zárolást, kivéve, ha írási zárat szerez. Vagyis a kritikus szakaszok írása és olvasása nem hajtható végre párhuzamosan, de a kritikus szakaszok olvasása igen [2] .

Megvalósítási algoritmusok

A szemaforok és mutexek legegyszerűbb megvalósítási algoritmusa egy bináris szemafor kapcsoló használata. A bejegyzést ennek a szemafornak kell védenie. Az első olvasási feladatnak egy kapcsolóval zárnia kell a szemafort, blokkolva az írási szálakat, a munkáját befejező utolsó feladatnak pedig fel kell szabadítania a szemafort, lehetővé téve az írási feladatok folytatását [5] . Ennek a megvalósításnak azonban van egy komoly problémája, amely a holtponthoz hasonlítható: az írási feladatok erőforrás-éhezése [6] .

Pszeudokód egy egyszerű olvasási-írási zárolási algoritmushoz
Inicializálás Olvasási feladat Írási feladat
kapcsoló = Switch() írási engedély = szemafor(1) zár (kapcsoló, írási engedély) // Az olvasási feladat kritikus része feloldás (kapcsoló, engedély-írás) rögzítés (írási engedély) // Az írási feladat kritikus része kiadás (írási engedély)

Az univerzális algoritmus, amely mentes a fent leírt problémától, tartalmaz egy A bináris szemaforkapcsolót az olvasási feladatok kritikus szakaszának megszervezéséhez, valamint egy forgókapcsolót, amely blokkolja az új olvasási feladatokat várakozó írók jelenlétében. Amikor megérkezik az első olvasandó feladat, egy kapcsolóval lefoglalja az A szemafort, megakadályozva az írást. Az írók számára az A szemafor védi az író kritikus részét, így ha az olvasók elkapják, minden író blokkolja a kritikus részbe való belépést. Az A szemafor írói feladatainak rögzítését és az azt követő írást azonban a forgószemafor védi. Ezért, ha egy írási feladat blokkolása következik be olvasók jelenléte miatt, a forgókapu blokkolódik az új olvasási feladatokkal együtt. Amint az utolsó olvasó befejezi a munkáját, a kapcsolószemafor felszabadul, és a sorban lévő első író blokkolása feloldásra kerül. Munkája végén elengedi a forgókapu szemaforját, ezzel ismét lehetővé téve az olvasási feladatok munkáját [7] .

Az univerzális olvasási-írási zárolási algoritmus pszeudokódja
Inicializálás Olvasási feladat Írási feladat
kapcsoló = Switch() írási engedély = szemafor(1) forgókapu = szemafor (1) megragad (forgókapu) kioldó (forgókapu) zár (kapcsoló, írási engedély) // Az olvasási feladat kritikus része feloldás (kapcsoló, engedély-írás) megragad (forgókapu) rögzítés (írási engedély) // Az írási feladat kritikus része elenged (forgókapu) kiadás (írási engedély)

Az operációs rendszer szintjén léteznek olvasási és írási szemaforok megvalósításai, amelyeket speciális módon módosítanak a tömeges használat hatékonyságának növelése érdekében. Az írási-olvasási zárak implementációi egyaránt alapulhatnak mutexeken és spinlockokon [4] .

Használati problémák

Míg az írási-olvasási zárolások javíthatják egyes algoritmusok sebességét, van egy rejtett probléma, amely akkor jelentkezik, ha az olvasási kérelmek sűrűsége egyenletes. Ebben az esetben az írási zárolás beszerzése korlátlan ideig késleltethető, ami az írási feladatok erőforrás-éhezését okozza [4] . Az írói feladatok erőforrás-éhezése a holtponthoz hasonlítható , mivel az adatok írása lehetetlen lesz, amíg új olvasási feladatok érkeznek. Ebben az esetben előfordulhat, hogy a probléma csak akkor lesz észrevehető, ha a rendszer terhelése nagyon magas, de a terhelés növekedésével jelentkezhet. A megoldás beépíthető az olvasási-írási zárolások megvalósításába, és minden új olvasási feladat blokkolását jelenti, ha legalább egy író vár a zárolásra [6] .

A blokkolás írásra emelése

A zárolási eszkaláció koncepciója lehetővé teszi, hogy a rögzített olvasási zárolást exkluzív írási zárolássá alakítsák. A zárolás akkor lép életbe, ha már nincs több olvasói feladat, ellenkező esetben a feladat blokkol, amíg az olvasói feladatok fel nem oldják a zárolást. A koncepció lehetővé teszi az írási zárolás visszaminősítését is olvasási zárolássá [8] . A koncepció azonban gyakran opcionális, és nem szükséges, hogy jelen legyen az egyes megvalósításokban.

Alkalmazás programozás

POSIX támogatás

A POSIXpthread_rwlock_t szabványban az írási-olvasási zárolásokat a fejlécfájl típusa jelöli pthread.h. A zárak bizonyos paramétereket adhatók meg attribútumokon keresztül, különösen, hogy egy zárolás definiálható folyamatok között vagy csak szálak között, és a folyamatok között elérhető zárolást írja elő a szabvány. Ha nincsenek olvasási feladatok, akkor az írási feladatok zárolási sorrendjét a kiválasztott ütemező házirend határozza meg. Az író és olvasó feladatok közötti zárakszerzési prioritást azonban nem határozza meg a szabvány [1] .

Win32 API támogatás

A Windows API -ban a zárakat SRWLOCKegy fejlécfájlból származó struktúra Synchapi.hés a vele való munkavégzéshez szükséges funkciók készlete képviseli. A zárakat úgy tervezték, hogy egyetlen folyamaton belül működjenek a szálakkal, és nem garantált a zárak beszerzése. A szolgáltatások közül a zár használatát egy feltételváltozóval együtt egy függvény SleepConditionVariableSRW()[9] támogatja .

Támogatás programozási nyelvekben

Olvasási-írási zárak az általános programozási nyelvekben
Nyelv Modul vagy könyvtár Adattípus
Xi pthread pthread_rwlock_t[egy]
C++ std std::shared_mutex[3]
C# System.Threading ReaderWriterLock[tíz]
Megy sync RWMutex[tizenegy]
Jáva java.base,java.util.concurrent.locks ReentrantReadWriteLock[12]
Rozsda std std::sync::RwLock[13]

Lásd még

Jegyzetek

  1. 1 2 3 4 5 Rendszerinterfészek indoklása, Általános információk, 2018 , Szálbővítmények.
  2. 1 2 3 Allen B. Downey, 2016 , 4.2 Író-olvasó probléma, p. 65.
  3. 1 2 C++17, 2017 , 33.4.3.4 Megosztott mutex típusok, p. 1373.
  4. ↑ 1 2 3 Oleg Tsiljurik. Kernel programozási eszközök: 73. rész. Párhuzamosság és szinkronizálás. Zárak. 1. rész . - www.ibm.com, 2013. - augusztus 13. — Hozzáférés időpontja: 2019.12.06.
  5. Allen B. Downey, 2016 , 4.2.2 Olvasó-író megoldás, p. 69-71.
  6. 1 2 Allen B. Downey, 2016 , 4.2.3 Éheztetés, p. 71.
  7. Allen B. Downey, 2016 , 4.2.5 Nem éhező olvasók-írók megoldás, p. 75.
  8. Szinkronizálás  : [ arch. 2020. 06. 24. ] // Boost 1.73.0 dokumentáció . — Hozzáférés időpontja: 2020.06.24.
  9. Michael Satran, McLean Schofield, Drew Batchelor, Bill Ticehurst. Vékony olvasó/író (SRW)  zárak . Microsoft dokumentumok . Microsoft (2018. május 31.). Letöltve: 2020. június 23. Az eredetiből archiválva : 2020. június 23.
  10. ReaderWriterLock osztály  // Microsoft Docs. – Microsoft . — Hozzáférés időpontja: 2020.06.23.
  11. Csomagszinkronizálás  : [ arch. 2020.06.23 . ] // A Go programozási nyelv. — Hozzáférés időpontja: 2020.06.23.
  12. Class ReentrantReadWriteLock  . Java API referencia . Jóslat. Letöltve: 2020. június 23. Az eredetiből archiválva : 2020. június 23.
  13. std::sync::RwLock  : [ arch. 06/23/2020 ] // Rozsdadokumentáció. - doc.rust-lang.org. — Hozzáférés időpontja: 2020.06.23.

Irodalom