Sdílet prostřednictvím


Multithreading: Jak používat synchronizační třídy

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.Není známa, jaká data vlákno pro čtení obdržení: stará data, nově zapsaná data či 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á CSemaphore 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.

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čování, jakou synchronizační třídu použít v různých situacích, naleznete v tématu Multithreading: Kdy použít synchronizační třídy.Další informace o synchronizaci naleznete v tématu Synchronizace ve Windows SDK. Další informace o více vláknech v knihovně MFC naleznete v tématu Multithreading s C++ a knihovnou MFC.

Viz také

Koncepty

Multithreading s použitím jazyka C++ a prostředí MFC