Quando dovremmo usare mutex e quando dovremmo usare il semaforo


Risposte:


92

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.


1
da aggiungere a: i semafori e il mutex sono due modi per fornire la sincronizzazione. semaforo, può essere più correlato alla segnalazione (es. scenario di problemi del produttore e del consumatore), e il mutex, può essere più correlato al consentire l'accesso a uno alla volta (diverse richieste di accesso alla risorsa condivisa, ma solo una concessa alla volta). [bell'articolo: geeksforgeeks.org/mutex-vs-semaphore/]
parasrish

57

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.


Ok, mi sono imbattuto anche in un semaforo binario. Quando dovremmo aver bisogno di entrare per il semaforo binario e quando dovremmo usare mutex?
Karthik Balaguru

Concettualmente, un semaforo binario è un mutex ed è equivalente a un normale semaforo con un conteggio. Potrebbero esserci differenze nelle implementazioni del concetto come l'efficienza o la proprietà della risorsa (può essere rilasciato da qualcuno diverso dal richiedente, che non sono d'accordo con BTW - una risorsa dovrebbe essere rilasciabile solo dal thread che l'ha rivendicata ).
paxdiablo

1
Un'altra potenziale differenza di implementazione è il mutex ricorsivo. Poiché esiste una sola risorsa, a un singolo thread può essere consentito di bloccarla più volte (purché lo rilasci anche tante volte). Non è così facile con una risorsa a più istanze poiché potresti non sapere se il thread desidera rivendicare un'altra istanza o la stessa istanza di nuovo.
paxdiablo

1
Risolvono un problema specifico. Il fatto che il problema si risolve è persone che non abbastanza Grok mutex, dovrebbe in alcun modo sminuire la soluzione :-)
paxdiablo

5
Un mutex è totalmente diverso da un semaforo binario. Scusate ma questa definizione è sbagliata
Peer Stritzinger

49

È 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


Gli URL di questo sito contengono caratteri funky e quindi non funzionano ... Ci sto lavorando
Peer Stritzinger

13

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


2
Hai ragione. Anche se stai usando un semaforo con un conteggio di uno, stai implicando qualcosa su ciò che stai facendo rispetto a se avessi usato un mutex.
Omnifarious

Non sono sicuro di essere d'accordo con questo, anche se non sono in disaccordo con tanta veemenza da farti un voto negativo :-) Dici che il modello di utilizzo dei semafori è notificare i thread ma è esattamente quello che fanno i mutex quando c'è un altro thread in attesa su di esso, ed esattamente ciò che i semafori non fanno quando non ci sono thread in 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.
paxdiablo

You say that the usage pattern of semaphores is to notify threadsUn punto sulla notifica ai thread. Puoi chiamare in sicurezza sem_postda un gestore di segnali ( pubs.opengroup.org/onlinepubs/009695399/functions/… ) ma non è consigliabile chiamare pthread_mutex_locke pthread_mutex_unlockda gestori di segnali ( manpages.ubuntu.com/manpages/lucid/man3/… )

@paxdiablo: C'è una grande differenza tra questo semaforo binario mutex è mantenere il conteggio dei riferimenti. Mutex o si può dire che qualsiasi mutex condizionale non mantiene alcun conteggio relativo al blocco dove come sempahore usa per mantenere il conteggio. Quindi sem_wait e sem_post mantengono il conteggio.
Prak

9

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


7

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.

  1. 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

  2. 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

  3. 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.


5

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.


5

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 be una funzione getc()per eseguire il calcolo c = a + b.

Ovviamente, non possiamo fare il c = a + bmeno 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 t3non fare il suo lavoro fino t1e t2hanno 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.


La vendita di biglietti è un ottimo esempio. L'esempio del semaforo è un po 'poco chiaro (per me comunque).
Prayagupd

1
@prayagupd L'esempio del semaforo consiste nel creare thread in un certo ordine, mentre la vendita di biglietti non richiede alcun ordine. Se ci sono tre persone: a, be c. Quando vengono a comprare i biglietti, non ci interessa affatto l'ordine di acquisto dei biglietti. Tuttavia, se facciamo un calcolo del genere: 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 + ya meno getxe getyabbiamo finito. In una parola, il semaforo viene utilizzato quando ci interessa l'ordine di esecuzione del multi-threading.
Yves

ti ho preso. Sembra simile alla barriera . Posso dire che aspetta fino a quando i thread xe ysono 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 reducefinché tutti mapi messaggi non sono stati completati.
Prayagupd

@prayagupd Sì. Si può dire che.
Yves

2

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


1

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.


1

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.


-1

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.