Quando dovremmo usare mutex e quando dovremmo usare il semaforo?
Quando dovremmo usare mutex e quando dovremmo usare il semaforo?
Risposte:
Ecco come ricordo quando usare cosa -
Semaforo: usa un semaforo quando (thread) vuoi dormire fino a quando un altro thread ti dice di svegliarti. Il semaforo "giù" si verifica in un thread (produttore) e il semaforo "su" (per lo stesso semaforo) si verifica in un altro thread (consumatore) ad esempio: nel problema produttore-consumatore, il produttore vuole dormire finché almeno uno slot del buffer è vuoto - solo il thread consumer può dire quando uno slot del buffer è vuoto.
Mutex: usa un mutex quando (thread) vuoi eseguire codice che non dovrebbe essere eseguito da nessun altro thread allo stesso tempo. Mutex "down" avviene in un thread e mutex "up" deve avvenire nello stesso thread in seguito. es: se stai eliminando un nodo da un elenco collegato globale, non vuoi che un altro thread si metta in giro con i puntatori mentre stai eliminando il nodo. Quando si acquisisce un mutex e si è impegnati a eliminare un nodo, se un altro thread tenta di acquisire lo stesso mutex, verrà messo in sospensione finché non si rilascia il mutex.
Spinlock: usa uno spinlock quando vuoi davvero usare un mutex ma il tuo thread non è autorizzato a dormire. eg: un gestore di interrupt all'interno del kernel del sistema operativo non deve mai dormire. Se lo fa, il sistema si bloccherà / andrà in crash. Se è necessario inserire un nodo in un elenco collegato condiviso a livello globale dal gestore degli interrupt, acquisire uno spinlock - inserire nodo - rilasciare spinlock.
Un mutex è un oggetto di mutua esclusione, simile a un semaforo ma che consente solo un armadietto alla volta e le cui restrizioni sulla proprietà possono essere più rigorose di un semaforo.
Può essere considerato equivalente a un normale semaforo di conteggio (con un conteggio di uno) e il requisito che può essere rilasciato solo dallo stesso thread che lo ha bloccato (a) .
Un semaforo, d'altra parte, ha un conteggio arbitrario e può essere bloccato da tanti armadietti contemporaneamente. E potrebbe non essere necessario che venga rilasciato dallo stesso thread che lo ha richiesto (ma, in caso contrario, è necessario monitorare attentamente chi ne ha la responsabilità, proprio come la memoria allocata).
Quindi, se hai più istanze di una risorsa (diciamo tre unità nastro), potresti usare un semaforo con un conteggio di 3. Nota che questo non ti dice quale di quelle unità nastro hai, solo che hai un certo numero.
Anche con i semafori, è possibile che un singolo armadietto blocchi più istanze di una risorsa, ad esempio per una copia da nastro a nastro. Se hai una risorsa (ad esempio una posizione di memoria che non vuoi corrompere), un mutex è più adatto.
Le operazioni equivalenti sono:
Counting semaphore Mutual exclusion semaphore
-------------------------- --------------------------
Claim/decrease (P) Lock
Release/increase (V) Unlock
A parte: nel caso in cui ti sei mai chiesto le bizzarre lettere usate per rivendicare e rilasciare semafori, è perché l'inventore era olandese. Probeer te verlagen significa provare a diminuire mentre verhogen significa aumentare.
(a) ... oppure può essere pensato come qualcosa di totalmente distinto da un semaforo, che può essere più sicuro dato i loro usi quasi sempre diversi.
È molto importante capire che un mutex non è un semaforo con conteggio 1!
Questo è il motivo per cui esistono cose come i semafori binari (che sono in realtà semafori con conteggio 1).
La differenza tra un Mutex e un semaforo binario è il principio di proprietà:
Un mutex viene acquisito da un'attività e quindi deve essere rilasciato anche dalla stessa attività. Ciò rende possibile risolvere diversi problemi con i semafori binari (rilascio accidentale, deadlock ricorsivo e inversione di priorità).
Avvertenza: ho scritto "rende possibile", se e come questi problemi vengono risolti dipende dall'implementazione del sistema operativo.
Poiché il mutex deve essere rilasciato dalla stessa attività, non è molto buono per la sincronizzazione delle attività. Ma se combinato con le variabili di condizione si ottengono blocchi di costruzione molto potenti per costruire tutti i tipi di primitive ipc.
Quindi la mia raccomandazione è: se hai mutex implementati in modo pulito e variabili di condizione (come con i pthread POSIX), usali.
Usa i semafori solo se si adattano esattamente al problema che stai cercando di risolvere, non provare a costruire altre primitive (es. Rw-blocca i semafori, usa mutex e variabili di condizione per questi)
Ci sono molti malintesi tra mutex e semafori. La migliore spiegazione che ho trovato finora è in questo articolo in 3 parti:
Mutex vs. semafori - Parte 1: semafori
Mutex vs. Semafori - Parte 2: Il Mutex
Mutex vs. Semaphores - Parte 3 (parte finale): Problemi di mutua esclusione
Mentre la risposta di @opaxdiablo è totalmente corretta, vorrei sottolineare che lo scenario di utilizzo di entrambe le cose è abbastanza diverso. Il mutex viene utilizzato per proteggere parti di codice dall'esecuzione simultanea, i semafori vengono utilizzati per un thread per segnalare l'esecuzione di un altro thread.
/* Task 1 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing);
/* Task 2 */
pthread_mutex_lock(mutex_thing);
// Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex
Lo scenario del semaforo è diverso:
/* Task 1 - Producer */
sema_post(&sem); // Send the signal
/* Task 2 - Consumer */
sema_wait(&sem); // Wait for signal
Vedere http://www.netrino.com/node/202 per ulteriori spiegazioni
sema_wait
:-) Secondo me, riguardano entrambe le risorse e la notifica consegnata ad altri thread è un effetto collaterale (molto importante, dal punto di vista delle prestazioni) del protezione.
You say that the usage pattern of semaphores is to notify threads
Un punto sulla notifica ai thread. Puoi chiamare in sicurezza sem_post
da un gestore di segnali ( pubs.opengroup.org/onlinepubs/009695399/functions/… ) ma non è consigliabile chiamare pthread_mutex_lock
e pthread_mutex_unlock
da gestori di segnali ( manpages.ubuntu.com/manpages/lucid/man3/… )
Vedi "The Toilet Example" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :
mutex:
È una chiave per un bagno. Una persona può avere la chiave - occupare il bagno - alla volta. Al termine, la persona dà (libera) la chiave alla persona successiva in coda.
Ufficialmente: "I mutex vengono in genere utilizzati per serializzare l'accesso a una sezione di codice di rientro che non può essere eseguito contemporaneamente da più di un thread. Un oggetto mutex consente solo a un thread in una sezione controllata, forzando altri thread che tentano di accedere a quella sezione per attendere che il primo thread sia uscito da quella sezione. " Rif: Symbian Developer Library
(Un mutex è in realtà un semaforo con valore 1.)
Semaforo:
È il numero di chiavi WC identiche gratuite. Ad esempio, supponiamo di avere quattro bagni con serrature e chiavi identiche. Il conteggio del semaforo - il conteggio delle chiavi - è impostato su 4 all'inizio (tutti e quattro i servizi igienici sono gratuiti), quindi il valore del conteggio viene diminuito man mano che le persone entrano. Se tutti i bagni sono pieni, ad es. non sono rimaste chiavi libere, il conteggio dei semafori è 0. Ora, quando eq. una persona lascia il bagno, il semaforo viene aumentato a 1 (una chiave gratuita) e viene consegnato alla persona successiva in coda.
Ufficialmente: "Un semaforo limita il numero di utenti simultanei di una risorsa condivisa fino a un numero massimo. I thread possono richiedere l'accesso alla risorsa (diminuendo il semaforo) e possono segnalare che hanno finito di utilizzare la risorsa (incrementando il semaforo). " Rif: Symbian Developer Library
Sto cercando di non sembrare buffo, ma non posso farci niente
La tua domanda dovrebbe essere qual è la differenza tra mutex e semafori? E per essere più precisi la domanda dovrebbe essere: "qual è la relazione tra mutex e semafori?"
(Avrei aggiunto quella domanda, ma sono sicuro al cento per cento che qualche moderatore troppo zelante l'avrebbe chiusa come duplicato senza capire la differenza tra differenza e relazione.)
Nella terminologia degli oggetti possiamo osservare che:
osservazione.1 Il semaforo contiene mutex
osservazione.2 Mutex non è semaforo e semaforo non è mutex.
Ci sono alcuni semafori che agiranno come se fossero mutex, chiamati semafori binari, ma NON sono mutex.
C'è un ingrediente speciale chiamato Signaling (posix usa condition_variable per quel nome), necessario per creare un semaforo dal mutex. Consideralo come una fonte di notifica. Se due o più thread sono iscritti alla stessa fonte di notifica, è possibile inviare loro un messaggio a UNO o a TUTTI, per svegliarsi.
Potrebbero esserci uno o più contatori associati ai semafori, che sono protetti da mutex. Lo scenario più semplice per il semaforo, c'è un singolo contatore che può essere 0 o 1.
Qui è dove la confusione si riversa come piogge monsoniche.
Un semaforo con un contatore che può essere 0 o 1 NON è mutex.
Mutex ha due stati (0,1) e una proprietà (attività). Il semaforo ha un mutex, alcuni contatori e una variabile di condizione.
Ora, usa la tua immaginazione, e ogni combinazione di utilizzo del contatore e quando segnalare può creare una specie di semaforo.
Contatore singolo con valore 0 o 1 e segnalazione quando il valore va a 1 E poi sblocca uno dei ragazzi in attesa del segnale == Semaforo binario
Contatore singolo con valore da 0 a N e che segnala quando il valore scende a meno di N e si blocca / attende quando il valore è N == Semaforo di conteggio
Contatore singolo con valore da 0 a N e che segnala quando il valore va a N e blocca / attende quando i valori sono inferiori a N == Semaforo barriera (beh, se non lo chiamano, dovrebbero.)
Ora alla tua domanda, quando usare cosa. (O piuttosto la versione corretta della domanda 3 quando usare mutex e quando usare il semaforo binario, poiché non c'è confronto con il semaforo non binario.) Usa mutex quando 1. vuoi un comportamento personalizzato, che non è fornito da binario semaforo, tali sono spin-lock o fast-lock o ricorsivi-lock. Di solito puoi personalizzare i mutex con attributi, ma personalizzare il semaforo non è altro che scrivere un nuovo semaforo. 2. vuoi primitivo leggero o più veloce
Usa semafori, quando quello che vuoi è esattamente fornito da esso.
Se non capisci cosa viene fornito dalla tua implementazione del semaforo binario, allora IMHO, usa mutex.
E infine leggi un libro piuttosto che fare affidamento solo su SO.
Penso che la domanda dovrebbe essere la differenza tra mutex e semaforo binario.
Mutex = È un meccanismo di blocco della proprietà, solo il thread che acquisisce il blocco può rilasciare il blocco.
Semaforo binario = È più un meccanismo di segnalazione, qualsiasi altro thread con priorità più alta, se lo desidera, può segnalare e prendere il blocco.
Mutex serve a proteggere la risorsa condivisa.
Il semaforo è inviare i thread.
Mutex:
Immagina che ci siano dei biglietti da vendere. Possiamo simulare un caso in cui molte persone acquistano i biglietti contemporaneamente: ogni persona è un filo per acquistare i biglietti. Ovviamente dobbiamo usare il mutex per proteggere i ticket perché è la risorsa condivisa.
Semaforo:
immagina di dover eseguire un calcolo come di seguito:
c = a + b;
Inoltre, abbiamo bisogno di una funzione geta()
per calcolare a
, una funzione getb()
per calcolare b
e una funzione getc()
per eseguire il calcolo c = a + b
.
Ovviamente, non possiamo fare il c = a + b
meno geta()
e getb()
abbiamo finito.
Se le tre funzioni sono tre thread, è necessario inviare i tre thread.
int a, b, c;
void geta()
{
a = calculatea();
semaphore_increase();
}
void getb()
{
b = calculateb();
semaphore_increase();
}
void getc()
{
semaphore_decrease();
semaphore_decrease();
c = a + b;
}
t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);
Con l'aiuto del semaforo, il codice di cui sopra può fare in modo che t3
non fare il suo lavoro fino t1
e t2
hanno fatto il loro lavoro.
In una parola, il semaforo serve a far eseguire i thread come un ordine logico mentre il mutex serve a proteggere la risorsa condivisa.
Quindi NON sono la stessa cosa anche se alcune persone dicono sempre che mutex è un semaforo speciale con il valore iniziale 1. Puoi anche dire così ma per favore nota che sono usati in casi diversi. Non sostituire l'uno con l'altro anche se puoi farlo.
x = getx(); y = gety(); z = x + y;
Per qualche ragione, usiamo tre thread per fare le tre cose, ora l'ordine delle discussioni è molto importante perché non possiamo fare x + y
a meno getx
e gety
abbiamo finito. In una parola, il semaforo viene utilizzato quando ci interessa l'ordine di esecuzione del multi-threading.
x
e y
sono completati, quindi calcola z = x + y
. So che Java ha CyclicBarrier
. Inoltre, non sono sicuro di poter dire che mapreduce
è anche un caso d'uso semaforo, perché non posso reduce
finché tutti map
i messaggi non sono stati completati.
Tutte le risposte di cui sopra sono di buona qualità, ma questa è solo da memorizzare.Il nome Mutex deriva da Mutuamente Esclusivo, quindi sei motivato a pensare a un blocco del mutex come Esclusione reciproca tra due come in uno solo alla volta, e se io posseduto lo puoi avere solo dopo che l'ho rilasciato. D'altronde questo caso non esiste perché Semaphore è proprio come un segnale stradale (che significa anche la parola Semaphore).
Come è stato sottolineato, un semaforo con un conteggio di uno è la stessa cosa di un semaforo "binario" che è la stessa cosa di un mutex.
Le cose principali che ho visto nei semafori con un conteggio maggiore di quello utilizzato sono le situazioni produttore / consumatore in cui hai una coda di una certa dimensione fissa.
Allora hai due semafori. Il primo semaforo è inizialmente impostato per essere il numero di elementi nella coda e il secondo semaforo è impostato su 0. Il produttore esegue un'operazione P sul primo semaforo, aggiunge alla coda. e fa un'operazione V sul secondo. Il consumatore esegue un'operazione P sul secondo semaforo, lo rimuove dalla coda e quindi esegue un'operazione V sul primo.
In questo modo il produttore viene bloccato ogni volta che riempie la coda e il consumatore viene bloccato ogni volta che la coda è vuota.
Un mutex è un caso speciale di un semaforo. Un semaforo consente a diversi thread di entrare nella sezione critica. Quando si crea un semaforo si definisce come possono essere consentiti i thread nella sezione critica. Ovviamente il tuo codice deve essere in grado di gestire diversi accessi a questa sezione critica.
Il semaforo binario e il Mutex sono diversi. Dal punto di vista del sistema operativo, un semaforo binario e un semaforo di conteggio vengono implementati nello stesso modo e un semaforo binario può avere un valore 0 o 1.
Mutex -> Può essere utilizzato solo per un unico scopo di mutua esclusione per una sezione critica di codice.
Semaforo -> Può essere utilizzato per risolvere una varietà di problemi. Un semaforo binario può essere utilizzato per la segnalazione e anche per risolvere il problema di mutua esclusione. Quando inizializzato a 0 , risolve il problema di segnalazione e quando inizializzato a 1 , risolve il problema di mutua esclusione .
Quando il numero di risorse è maggiore e deve essere sincronizzato, possiamo utilizzare il semaforo di conteggio.
Nel mio blog, ho discusso in dettaglio questi argomenti.
https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html