Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A szálak közötti erőforrás-hozzáférés szinkronizálása gyakori probléma a többszálas alkalmazások írásakor. Ha két vagy több szál egyszerre fér hozzá ugyanazokhoz az adatokhoz, az nemkívánatos és kiszámíthatatlan eredményekhez vezethet. Az egyik szál például frissítheti egy struktúra tartalmát, míg egy másik szál ugyanannak a struktúrának a tartalmát olvassa. Nem ismert, hogy az olvasószál milyen adatokat fog kapni: a régi adatokat, az újonnan írt adatokat, vagy esetleg mindkettőt. Az MFC számos szinkronizálási és szinkronizálási hozzáférési osztályt biztosít a probléma megoldásához. Ez a témakör ismerteti az elérhető osztályokat, és azt, hogy hogyan hozhat létre szálbiztos osztályokat egy tipikus többszálas alkalmazásban.
Egy tipikus többszálú alkalmazásnak van egy osztálya, amely egy olyan erőforrást jelöl, amelyet meg kell osztani a szálak között. A megfelelően megtervezett, teljesen szálbiztos osztály nem követeli meg a szinkronizálási függvények meghívását. Az osztály mindent belsőleg kezel, így Ön az osztály legmegfelelőbb használatára koncentrálhat, és nem arra, hogy hogyan sérülhet meg. A teljes szálbiztos osztály létrehozásának hatékony módszere a szinkronizálási osztály erőforrásosztályba való egyesítése. A szinkronizálási osztályok egyesítése a megosztott osztályba egyszerű folyamat.
Példaként vegyünk egy alkalmazást, amely egy csatolt fióklistát tart fenn. Ez az alkalmazás legfeljebb három fiók vizsgálatát teszi lehetővé külön ablakban, de egy adott időpontban csak egy frissíthető. A fiók frissítésekor a frissített adatokat a rendszer a hálózaton keresztül továbbítja egy adatarchívumnak.
Ez a példaalkalmazás mindhárom szinkronizálási osztályt használja. Mivel egyszerre legfeljebb három fiók vizsgálatát teszi lehetővé, a CSemaphore használatával korlátozza a hozzáférést három nézetobjektumhoz. Amikor megkísérli megtekinteni a negyedik fiókot, az alkalmazás vagy megvárja, amíg az első három ablak valamelyike bezárul, vagy sikertelen lesz. Egy fiók frissítésekor az alkalmazás a CCriticalSection használatával biztosítja, hogy egyszerre csak egy fiók legyen frissítve. A frissítés sikeressége után jelzi a CEvent-et, amely felszabadít egy szálat, ami az esemény jelzésére vár. Ez a szál elküldi az új adatokat az adatarchívumnak.
Thread-Safe osztály tervezése
Az osztály teljes szálbiztossá tétele érdekében először adja hozzá a megfelelő szinkronizálási osztályt a megosztott osztályokhoz adattagként. Az előző fiókkezelési példában egy CSemaphore adattagot adna hozzá a nézetosztályhoz, egy CCriticalSection adattagot a csatolt lista osztályhoz, és egy CEvent adattagot adna hozzá az adattárolási osztályhoz.
Ezután adjon hozzá szinkronizálási hívásokat az összes olyan tagfüggvényhez, amely módosítja az osztály adatait, vagy egy szabályozott erőforráshoz fér hozzá. Minden függvényben létre kell hoznia egy CSingleLock vagy CMultiLock objektumot, és meg kell hívnia az objektum függvényét Lock . Amikor a zárolási objektum kiesik a hatókörből és megsemmisül, az objektum destruktora meghívja a Unlock függvényt, ezzel felszabadítva az erőforrást. Természetesen közvetlenül is hívhat Unlock , ha szeretné.
Az ilyen módon megtervezett szálbiztos osztály lehetővé teszi, hogy egy többszálas alkalmazásban olyan könnyen használható legyen, mint egy nem szálbiztos osztály, de magasabb szintű biztonsággal. A szinkronizálási objektum és a szinkronizálási hozzáférési objektum erőforrásosztályba való beágyazása a teljes szálbiztos programozás minden előnyét biztosítja a szinkronizálási kód fenntartása nélkül.
Az alábbi példakód bemutatja ezt a módszert egy adattaggal, m_CritSection (amelynek típusa CCriticalSection), amely a megosztott erőforrásosztályban kerül deklarálásra, valamint egy CSingleLock objektummal. A megosztott erőforrás szinkronizálását (amely CWinThread-ból származik) egy CSingleLock objektum létrehozásával kísérlik meg, amelyhez a m_CritSection objektum címét használják. Megkísérli zárolni az erőforrást, és ha ez sikerül, a közös objektumon végez munkát. Ha a munka befejeződött, az erőforrást egy hívás segítségével feloldjuk.Unlock
CSingleLock singleLock(&m_CritSection);
singleLock.Lock();
// resource locked
//.usage of shared resource...
singleLock.Unlock();
Megjegyzés:
CCriticalSectiona többi MFC-szinkronizálási osztálytól eltérően nincs lehetőség időzított zárolási kérésre. A szál szabaddá válásának várakozási ideje végtelen.
Ennek a megközelítésnek az hátránya, hogy az osztály kissé lassabb lesz, mint ugyanaz az osztály a szinkronizálási objektumok hozzáadása nélkül. Ha fennáll az esély arra, hogy egynél több szál is törli az objektumot, előfordulhat, hogy az egyesített megközelítés nem mindig működik. Ebben az esetben jobb, ha külön szinkronizálási objektumokat tart fenn.
A különböző helyzetekben használandó szinkronizálási osztály meghatározásával kapcsolatos információkért lásd : Többszálúság: Mikor érdemes használni a szinkronizálási osztályokat. A szinkronizálásról további információt a Szinkronizálás a Windows SDK-ban című témakörben talál. Az MFC többszálú támogatásáról további információt a C++ és az MFC többszálú használata című témakörben talál.