Szálkezelés : mutex vs CriticalSection

Szálkezelés : mutex vs CriticalSection
2011-02-13T18:56:32+01:00
2011-02-13T20:17:30+01:00
2022-11-20T20:00:33+01:00
Alonso
Elolvastam pár weblapot, C++ szálkezeléssel kapcsolatban, és a mutexekkel kapcsolatban van egy kis fogalmi zavarom. Két weblapról beszélnék most :

Multithreading Tutorial - CodeProject

illetve

Advanced C++ with Examples: Another Multi-Threading example with Mutex

Az első weblapon a Producer/Consumer résznél a Part2Listing1 programjára hivatkozik, amit letöltöttem, és kipróbáltam - mutexekkel, eventekkel dolgozik. Van benne egy ilyen rész :
#ifdef WITH_SYNCHRONIZATION HANDLE m_hMutex; HANDLE m_hEvent; #endif
A kódban a CRITICAL_SECTION rész sehol nincs leirva, se az, hogy EnterCriticalSection, stb. Nagyjából értem.
Ezzel szemben a 2. weblapon, ahol Singletonos multithreadet használ, mutexnek nevezi a class-t, de leirja, hogy EnterCriticalSection, LeaveCriticalSection, stb...

Most akkor ha mutexet használunk, akkor kell hivni az EnterCriticalSection, és a hozzá hasonló parancsokat, vagy mutexeknél ilyen nincsen ?

üdv, Alonso
Mutasd a teljes hozzászólást!
Elég idétlenül nevezték el. Még ilyet sem hallottam, hogy egy kizárólag lockolásra tervezett osztályt, amely egyetlen critical section-t használ, a mutex nevet adják neki. Gondolom ez zavart be, hogy létezik mutex és létezik critical section is.

Szóval, mit csinál a cs? Amikor egy szálban egy EnterCriticalSection() híváshoz ér a kódod, akkor ez az api leellenőrzi, hogy a cs le van-e foglalva. Ha le van foglalva, akkor megáll és addig vár, amíg a cs-t nem szabadítja fel az aki lefoglalta. Lehet nem magyarázom elég jól, inkább írok egy pici példát:
DWORD ThreadFunc( void *pParam ) { ... EnterCriticalSection( &cs ); // itt kell legyenek az olyan dolgok, amiket nem szabad egyszerre // 2 vagy tobb szal piszkalja // peldaul: WriteFile( .... ); LeaveCriticalSection( &cs ); ... }
Tegyük fel, hogy van egy mittomén 2 szálas programod. Mindkét szál függvénye a fenti, és ugyanabba a file-ba kell írniuk. Ugye egyszerre ezt nagyon nem lenne ajánlatos. Ezért bevezetünk egy CRITICAL_SECTION-t.
Tételezzük fel, hogy az első szál épp írja a file-t. Ez azt jelenti a fennebbi kód szerint, hogy meghívódott az EnterCriticalSection() és ezáltal a cs blokkolva lesz. Ha most megérkezne a második thread, akkor az EnterCriticalSection()-t hívva ez a függvény blokkolva lesz, addig amíg az első szál nem lép túl a LeaveCriticalSection() api-n, aminek az a dolga, hogy a cs-t feloldja. Ugye ha az 1. szál már ideért, akkor a fileba írás az ő részéről már befejeződött.
Természetesen mielőtt a szálakat elindítod, kéne egy InitializeCriticalSection() majd amikor mindkettő leállt, akkor egy DeleteCriticalSection().
Ugyanazt a cs-t használhatod több szálban is. Tipikusan egy producer/consumer páros is ilyen kéne legyen.
Nézz visza a megoldott témáimba, elég sokszor segítettem a szálakkal kapcsolatban, nemcsak C, hanem Delphi, VB, C, C++ -ban is.
Hagyd a francba azokat az osztályokat, csak megzavar! Annyit kell csinálnod, amit a fennebb írtam. De inkább még egyszer:

InitializeCriticalSection() ... EnterCriticalSection() LeaveCriticalSection() EnterCriticalSection() LeaveCriticalSection() EnterCriticalSection() LeaveCriticalSection() ... DeleteCriticalSection()
Ebben a sorrendben.

Vigyázz, nehogy elfelejtsd valamelyik LeaveCriticalSection() hívást, mert akkor abba a kódrészbe többet soha nem lép be senki!


megj:
A cs rövidítés alatt critical section-t értettem.


---
szerkesztettem egy párszor, remélem így érthetőbb.
Mutasd a teljes hozzászólást!

  • A 1. weblapnál használ eventeket(a 2. példaprogramjánál, amikor mutexekkel dolgozik), mig a 2. weblapnál nem, pedig az is mutexes. Melyik a jó akkor ?
    Mutasd a teljes hozzászólást!
  • Ahogy én látom, ez két különböző eszköz ugyanannak a feladatnak a megoldására, válaszd ki az egyiket, és használd azt.
    Mutasd a teljes hozzászólást!
  • Oké, hogy mindakét kód működik, és egy problémát az első és második megközelitéssel is meg lehet oldani, de ha arról van szó, hogy mutex, vagy mutexet kell használni, akkor az "EnterCriticalSection"-os megközelitést kell használni, vagy a másikat, a "WaitForSingleObject megközelitést" ? A két kódból nem tudom most, hogy melyik a mutexes megközelités
    Mutasd a teljes hozzászólást!
  • Hát, ha Critial Section-t akarsz használni, akkor olyasmi hívásokra lesz szükséged, amiknek a nevében benne van, hogy CriticalSection (Enter, Leave); ha meg mutexet, akkor értelemszerűen CreateMutex és a többi.

    Synchronization Functions (Windows)
    Mutasd a teljes hozzászólást!
  • Elég idétlenül nevezték el. Még ilyet sem hallottam, hogy egy kizárólag lockolásra tervezett osztályt, amely egyetlen critical section-t használ, a mutex nevet adják neki. Gondolom ez zavart be, hogy létezik mutex és létezik critical section is.

    Szóval, mit csinál a cs? Amikor egy szálban egy EnterCriticalSection() híváshoz ér a kódod, akkor ez az api leellenőrzi, hogy a cs le van-e foglalva. Ha le van foglalva, akkor megáll és addig vár, amíg a cs-t nem szabadítja fel az aki lefoglalta. Lehet nem magyarázom elég jól, inkább írok egy pici példát:
    DWORD ThreadFunc( void *pParam ) { ... EnterCriticalSection( &cs ); // itt kell legyenek az olyan dolgok, amiket nem szabad egyszerre // 2 vagy tobb szal piszkalja // peldaul: WriteFile( .... ); LeaveCriticalSection( &cs ); ... }
    Tegyük fel, hogy van egy mittomén 2 szálas programod. Mindkét szál függvénye a fenti, és ugyanabba a file-ba kell írniuk. Ugye egyszerre ezt nagyon nem lenne ajánlatos. Ezért bevezetünk egy CRITICAL_SECTION-t.
    Tételezzük fel, hogy az első szál épp írja a file-t. Ez azt jelenti a fennebbi kód szerint, hogy meghívódott az EnterCriticalSection() és ezáltal a cs blokkolva lesz. Ha most megérkezne a második thread, akkor az EnterCriticalSection()-t hívva ez a függvény blokkolva lesz, addig amíg az első szál nem lép túl a LeaveCriticalSection() api-n, aminek az a dolga, hogy a cs-t feloldja. Ugye ha az 1. szál már ideért, akkor a fileba írás az ő részéről már befejeződött.
    Természetesen mielőtt a szálakat elindítod, kéne egy InitializeCriticalSection() majd amikor mindkettő leállt, akkor egy DeleteCriticalSection().
    Ugyanazt a cs-t használhatod több szálban is. Tipikusan egy producer/consumer páros is ilyen kéne legyen.
    Nézz visza a megoldott témáimba, elég sokszor segítettem a szálakkal kapcsolatban, nemcsak C, hanem Delphi, VB, C, C++ -ban is.
    Hagyd a francba azokat az osztályokat, csak megzavar! Annyit kell csinálnod, amit a fennebb írtam. De inkább még egyszer:

    InitializeCriticalSection() ... EnterCriticalSection() LeaveCriticalSection() EnterCriticalSection() LeaveCriticalSection() EnterCriticalSection() LeaveCriticalSection() ... DeleteCriticalSection()
    Ebben a sorrendben.

    Vigyázz, nehogy elfelejtsd valamelyik LeaveCriticalSection() hívást, mert akkor abba a kódrészbe többet soha nem lép be senki!


    megj:
    A cs rövidítés alatt critical section-t értettem.


    ---
    szerkesztettem egy párszor, remélem így érthetőbb.
    Mutasd a teljes hozzászólást!
  • Oké, köszi, értem. Lehet, ezzel kapcsolatban hamarosan kérdezek még, de akkor új topicban, de ugyanezekre a weblapokra és kódokra fogok hivatkozni
    Mutasd a teljes hozzászólást!
  • oké, köszönöm !
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd