GNU/Linux >> Znalost Linux >  >> Linux

Jaký je rozdíl mezi mutexem a kritickou sekcí?

Critical Section a Mutex nejsou specifické pro operační systém, jejich koncepty multithreading/multiprocessing.

Kritická sekce Je kus kódu, který se musí v daném okamžiku spustit pouze sám o sobě (například existuje 5 vláken běžících současně a funkce nazvaná "critical_section_function", která aktualizuje pole... nechcete, aby všech 5 vláken aktualizovalo pole najednou. Když tedy program spouští kritickou_funkci_sekce(), žádné z ostatních vláken nesmí spouštět funkci kritické_sekce.

mutex* Mutex je způsob implementace kódu kritické sekce (přemýšlejte o tom jako o tokenu... vlákno jej musí vlastnit, aby spustilo kód kritické sekce)


Pro Windows jsou kritické sekce lehčí než mutexy.

Mutexy mohou být sdíleny mezi procesy, ale výsledkem je vždy systémové volání jádra, které má určitou režii.

Kritické sekce lze použít pouze v rámci jednoho procesu, ale mají tu výhodu, že se přepnou do režimu jádra pouze v případě sporu - Uncontended purchases, což by měl být běžný případ, jsou neuvěřitelně rychlé. V případě sporu vstupují do jádra a čekají na nějaké synchronizační primitivum (jako událost nebo semafor).

Napsal jsem rychlou ukázkovou aplikaci, která porovnává čas mezi nimi dvěma. V mém systému za 1 000 000 bezkonkurenčních akvizic a uvolnění zabere mutex jednu sekundu. Kritická sekce trvá ~50 ms pro 1 000 000 akvizic.

Zde je testovací kód, spustil jsem to a dostal jsem podobné výsledky, pokud je mutex první nebo druhý, takže žádné další efekty nevidíme.

HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
CRITICAL_SECTION critSec;
InitializeCriticalSection(&critSec);

LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER start, end;

// Force code into memory, so we don't see any effects of paging.
EnterCriticalSection(&critSec);
LeaveCriticalSection(&critSec);
QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    EnterCriticalSection(&critSec);
    LeaveCriticalSection(&critSec);
}

QueryPerformanceCounter(&end);

int totalTimeCS = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);

// Force code into memory, so we don't see any effects of paging.
WaitForSingleObject(mutex, INFINITE);
ReleaseMutex(mutex);

QueryPerformanceCounter(&start);
for (int i = 0; i < 1000000; i++)
{
    WaitForSingleObject(mutex, INFINITE);
    ReleaseMutex(mutex);
}

QueryPerformanceCounter(&end);

int totalTime = (int)((end.QuadPart - start.QuadPart) * 1000 / freq.QuadPart);

printf("Mutex: %d CritSec: %d\n", totalTime, totalTimeCS);

Kromě ostatních odpovědí jsou následující podrobnosti specifické pro kritické části oken:

  • při absenci sporu je získání kritické sekce stejně jednoduché jako InterlockedCompareExchange operace
  • struktura kritické sekce ponechává prostor pro mutex. Zpočátku je nepřiděleno
  • pokud mezi vlákny dojde ke sporu o kritickou sekci, bude mutex přidělen a použit. Výkon kritické sekce se sníží na výkon mutex
  • Pokud očekáváte vysokou hádku, můžete přidělit kritickou sekci s uvedením počtu roztočení.
  • pokud dojde ke sporu o kritickou sekci s počtem otáček, vlákno pokoušející se získat kritickou sekci se bude točit (zaneprázdněno-čekat) po tolik cyklů procesoru. To může vést k lepšímu výkonu než v režimu spánku, protože počet cyklů k provedení přepnutí kontextu do jiného vlákna může být mnohem vyšší než počet cyklů, které vlastní vlákno uvolní mutex
  • pokud počet otočení vyprší, mutex bude přidělen
  • když vlastnící vlákno uvolní kritickou sekci, je nutné zkontrolovat, zda je mutex přidělen, pokud ano, nastaví mutex tak, aby uvolnil čekající vlákno.

V linuxu si myslím, že mají "spin lock", který slouží k podobnému účelu jako kritická sekce s počtem otáček.


Z teoretického hlediska je kritická sekce kus kódu, který nesmí být spouštěn více vlákny najednou, protože kód přistupuje ke sdíleným zdrojům.

Mutex je algoritmus (a někdy i název datové struktury), který se používá k ochraně kritických sekcí.

Semafory a monitory jsou běžné implementace mutexu.

V praxi je ve Windows k dispozici mnoho implementací mutexů. Liší se především v důsledku své implementace úrovní zamykání, rozsahem, náklady a výkonem na různých úrovních sporu. Graf nákladů na různé implementace mutexů naleznete v části CLR Inside Out – Použití souběžnosti pro škálovatelnost.

Dostupná synchronizační primitiva.

  • Monitorovat
  • Mutex
  • Semafor
  • ReaderWriterLock
  • ReaderWriterLockSlim
  • Zablokováno

lock(object) příkaz je implementován pomocí Monitor - viz MSDN pro referenci.

V posledních letech se provádí velký výzkum neblokující synchronizace. Cílem je implementovat algoritmy bez uzamčení nebo bez čekání. V takových algoritmech proces pomáhá jiným procesům dokončit jejich práci, takže proces může konečně dokončit svou práci. V důsledku toho může proces dokončit svou práci, i když ostatní procesy, které se pokusily nějakou práci provést, zamrznou. Při použití zámků neuvolní své zámky a zabrání dalším procesům v pokračování.


Linux
  1. Rozdíl mezi [[ $a ==Z* ]] a [ $a ==Z* ]?

  2. Jaký je rozdíl mezi Redhat a centOS?

  3. Jaký je rozdíl mezi vlákny NPTL a POSIX?

  1. Jaký je rozdíl mezi strtok_r a strtok_s v C?

  2. Jaký je rozdíl mezi fsck a e2fsck?

  3. Jaký je rozdíl mezi adduser a useradd?

  1. Jaký je rozdíl mezi ls a l?

  2. Jaký je rozdíl mezi $(CC) a $CC?

  3. Jaký je rozdíl mezi unlink a rm?