Multithreading: Způsob použití třídy synchronizace
Synchronizační prostředek přístupu mezi vlákny je obecným problémem při psaní aplikací s více vlákny.Mají-li dva nebo více vlákna současně přístup, mohou stejná data vést k nežádoucím a nepředvídatelným výsledkům.Například, jedno vlákno může aktualizovat obsah struktury, zatímco jiné vlákno čte obsahy stejné struktury.Obdrží podproces čtení dat neznámý: stará data nově písemných údajů nebo případně kombinaci obou.Knihovna MFC poskytuje řadu synchronizačních tříd a tříd synchronizačního přístupu na pomoc při řešení tohoto problému.Toto téma vysvětluje třídy, které jsou k dispozici a jak je použít k tříd bezpečných pro přístup z více vláken v typické aplikaci s více vlákny.
Typická aplikace s více vlákny má třídu, která představuje prostředek ke sdílení mezi vlákny.Správně navržená třída plně bezpečná pro přístup z více vláken nevyžaduje, aby jste volali jakékoliv funkce synchronizace.Vše je zpracováváno interně ke třídě, což Vám umožní soustředit se na to, jak nejlépe využít třídu, ne o to jak by mohlo dojít k poškození.Efektivní technika pro vytvoření třídy plně bezpečné pro přístup z více vláken je sloučit synchronizační třídu do třídy prostředků.Sloučení tříd synchronizace do sdílené třídy je přímočarý proces.
Jako příklad si vezměme aplikaci, která udržuje propojený seznam účtů.Tato aplikace umožňuje prohlížet až tři účty v samostatných oknech, ale pouze jeden lze v jednom čase aktualizovat.Při aktualizaci účtu jsou aktualizovaná data odeslána přes síť do datového archivu.
Tato ukázková aplikace používá všechny tři typy tříd synchronizace.Protože umožňuje prohlížení až tří účtů v jednom okamžiku, používá 78w43c88(v=vs.110).md pro omezení přístupu ke třem objektům zobrazení.Při pokusu o zobrazení čtvrtého účtu aplikace buď čeká, dokud se jedno z prvních tří oken nezavře, nebo selže.Při aktualizaci účtu používá aplikace CCriticalSection k zajištění, že pouze jeden účet je aktualizován v jednu dobu.Po úspěšné aktualizaci signalizuje CEvent, což uvolní vlákno, čekající na signál události.Toto vlákno odesílá nová data do archivu dat.
Navrhování třídy bezpečné pro přístup z více vláken
Chcete-li, aby třída byla plně bezpečná přístup z více vláken, nejprve přidejte příslušnou synchronizační třídu ke sdíleným třídám jako datový člen.V předchozím příkladu správy účtu měl být přidán datový člen CSemaphore do zobrazení třídy, datový člen CCriticalSection by měl být přidán k propojovacímu seznamu třídy a datový člen CEvent by měl být přidán do třídy úložiště dat.
Dále přidejte synchronizaci volání ke všem členským funkcím, které mění data ve třídě nebo v řízeném prostředku.V každé funkci by jste měli vytvořit buď objekt CSingleLock nebo objekt CMultiLock a volat tento objekt funkcí Lock.Když zámek objektu přejde z rozsahu a je zničen, volání destruktoru objektu Unlock pro vás uvolní prostředek. Samozřejmě můžete volat přímo Unlock chcete-li.
Navrhování Vaší třídy bezpečné pro přístup z více vláken tímto způsobem umožňuje použít více vláknovou aplikaci stejně snadno jako třídu bez bezpečného přístupu s více vláken, ale s vyšší úrovní bezpečnosti.Zapouzdření synchronizace objektu a synchronizace přístupu objektu do třídy prostředku poskytuje všechny výhody programování, které je plně bezpečné pro přístup z více vláken, bez nevýhody udržování synchronizace kódu.
Následující příklad kódu ukazuje tuto metodu používající datový člen m_CritSection (typu CCriticalSection), deklarované ve třídě sdíleného prostředku a objektu CSingleLock. Synchronizace sdíleného prostředku (odvozená od CWinThread) je pokus o vytvoření objektu CSingleLock, použitím adresy objektu m_CritSection. Pokus je vyroben k uzamčení prostředku a pokud byl získán, práce je provedena na sdíleném objektu.Po dokončení práce je prostředek odemknut s voláním Unlock.
CSingleLock singleLock(&m_CritSection);
singleLock.Lock();
// resource locked
//.usage of shared resource...
singleLock.Unlock();
[!POZNÁMKA]
CCriticalSection na rozdíl od jiné knihovny MFC třídy synchronizace nemají možnost časově uzamknout žádost. Čekací lhůta pro uvolnění vlákna je neomezená.
Nevýhody tohoto přístupu jsou, že třída bude o něco pomalejší, než třída bez přidání objektů synchronizace.Také pokud je tam šance, že více než jedno vlákno smazalo objekt, sloučený přístup nemusí vždy fungovat.V takovém případě je lepší udržovat samostatné objekty synchronizace.
Informace o určení, které třídy synchronizace v různých situacích, v při souběžném: použití třídy synchronizace.Další informace o synchronizaci naleznete v tématu Synchronizace ve Windows SDK. Pro více informací o podpoře více vláken v knihovně MFC si prohlédněte Multithreading s C++ a knihovnou MFC.