GNU/Linux >> Linux Esercitazione >  >> Linux

Qual è la differenza tra mutex e sezione critica?

Critical Section e Mutex non sono specifici del sistema operativo, i loro concetti di multithreading/multiprocessing.

Sezione critica È un pezzo di codice che deve essere eseguito solo da solo in un dato momento (ad esempio, ci sono 5 thread in esecuzione contemporaneamente e una funzione chiamata "critical_section_function" che aggiorna un array... non vuoi che tutti e 5 i thread aggiornino il array in una sola volta. Quindi, quando il programma esegue critical_section_function(), nessuno degli altri thread deve eseguire la loro critical_section_function.

mutex* Mutex è un modo per implementare il codice della sezione critica (pensalo come un token... il thread deve possederne il possesso per eseguire il codice_sezione_critica)


Per Windows, le sezioni critiche sono più leggere dei mutex.

I mutex possono essere condivisi tra i processi, ma risultano sempre in una chiamata di sistema al kernel che ha un certo sovraccarico.

Le sezioni critiche possono essere utilizzate solo all'interno di un processo, ma hanno il vantaggio di passare alla modalità kernel solo in caso di contesa:le acquisizioni non contese, che dovrebbero essere il caso comune, sono incredibilmente veloci. In caso di contesa, entrano nel kernel per attendere qualche primitiva di sincronizzazione (come un evento o un semaforo).

Ho scritto una rapida app di esempio che confronta il tempo tra loro due. Sul mio sistema per 1.000.000 di acquisizioni e rilasci non contesi, un mutex impiega più di un secondo. Una sezione critica richiede circa 50 ms per 1.000.000 di acquisizioni.

Ecco il codice di test, l'ho eseguito e ho ottenuto risultati simili se mutex è il primo o il secondo, quindi non vediamo altri effetti.

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);

Oltre alle altre risposte, i seguenti dettagli sono specifici delle sezioni critiche su Windows:

  • in assenza di contesa, acquisire una sezione critica è semplice come un InterlockedCompareExchange operazione
  • la struttura della sezione critica contiene spazio per un mutex. Inizialmente non è allocato
  • se c'è conflitto tra i thread per una sezione critica, il mutex sarà allocato e usato. Le prestazioni della sezione critica si ridurranno a quelle del mutex
  • se prevedi una contesa elevata, puoi allocare la sezione critica specificando un numero di spin.
  • se c'è conflitto su una sezione critica con un numero di spin, il thread che tenta di acquisire la sezione critica girerà (busy-wait) per quel numero di cicli del processore. Ciò può comportare prestazioni migliori rispetto alla sospensione, poiché il numero di cicli per eseguire un cambio di contesto a un altro thread può essere molto più elevato del numero di cicli impiegati dal thread proprietario per rilasciare il mutex
  • se il numero di spin scade, il mutex verrà allocato
  • quando il thread proprietario rilascia la sezione critica, è necessario verificare se il mutex è allocato, in tal caso imposterà il mutex per rilasciare un thread in attesa

In Linux, penso che abbiano uno "spin lock" che ha uno scopo simile alla sezione critica con un conteggio degli spin.


Da un punto di vista teorico, una sezione critica è un pezzo di codice che non deve essere eseguito da più thread contemporaneamente perché il codice accede a risorse condivise.

Un mutex è un algoritmo (ea volte il nome di una struttura dati) utilizzato per proteggere sezioni critiche.

Semafori e monitor sono implementazioni comuni di un mutex.

In pratica ci sono molte implementazioni mutex disponibili in Windows. Differiscono principalmente in conseguenza della loro implementazione per il loro livello di blocco, i loro ambiti, i loro costi e le loro prestazioni in diversi livelli di contesa. Consulta CLR Inside Out -Utilizzo della concorrenza per la scalabilità per un grafico dei costi delle diverse implementazioni di mutex.

Primitive di sincronizzazione disponibili.

  • Controlla
  • Mutex
  • Semaforo
  • Blocco ReaderWriter
  • ReaderWriterLockSlim
  • Interbloccato

Il lock(object) l'istruzione è implementata usando un Monitor - vedi MSDN per riferimento.

Negli ultimi anni sono state fatte molte ricerche sulla sincronizzazione non bloccante. L'obiettivo è implementare gli algoritmi in modo lock-free o wait-free. In tali algoritmi un processo aiuta altri processi a terminare il proprio lavoro in modo che il processo possa finalmente terminare il proprio lavoro. Di conseguenza un processo può terminare il proprio lavoro anche quando altri processi, che hanno tentato di eseguire del lavoro, si bloccano. Usando i blocchi, non rilascerebbero i loro blocchi e impedirebbero ad altri processi di continuare.


Linux
  1. Qual è la differenza tra InnoDB e MyISAM?

  2. Qual è la differenza tra Git Switch e Checkout?

  3. Qual è la differenza tra strtok_r e strtok_s in C?

  4. Qual è la differenza tra $(CC) e $CC?

  5. Qual è la differenza tra route e ip route?

Qual è la differenza tra Linux e Unix?

Qual è la differenza tra Login e Non-Login Shell

Qual è la differenza tra il comando apt e apt-get?

Che cos'è un hypervisor? Qual è la differenza tra il tipo 1 e 2?

Qual è la differenza tra curl e Wget?

Qual è la differenza tra unlink e rm?