Differenza tra semaforo binario e mutex


819

C'è qualche differenza tra un semaforo binario e un mutex o sono essenzialmente gli stessi?


11
Sono semanticamente uguali, ma in pratica noterai strane differenze (specialmente su Windows).
Michael Foukarakis,

5
@Michael Foukarakis: quali sono le strane differenze?
Philipp,

2
Suppongo che strano non fosse l'espressione corretta. Un mutex supporta anche la proprietà e talvolta il rientro. Questo è il caso di Windows. Inoltre, i semafori in Windows sono implementati sopra gli oggetti Event, tuttavia, non sono sicuro delle implicazioni pratiche di questo.
Michael Foukarakis,


2
@philipxy Ha nascosto 'rn' al posto di 'm'.
Mooncrater,

Risposte:


691

NON sono la stessa cosa. Sono usati per scopi diversi!
Sebbene entrambi i tipi di semafori abbiano uno stato pieno / vuoto e utilizzino la stessa API, il loro utilizzo è molto diverso.

Semafori di esclusione
reciproca I semafori di esclusione reciproca vengono utilizzati per proteggere le risorse condivise (struttura dei dati, file, ecc.).

Un semaforo Mutex è "posseduto" dall'attività che lo prende. Se l'attività B tenta di emettere un mutex attualmente trattenuto dall'attività A, la chiamata dell'attività B restituirà un errore e fallirà.

I mutex usano sempre la seguente sequenza:

  - SemTake
  - Sezione critica
  - SemGive

Qui c'è un semplice esempio:

  Discussione A Discussione B
   Prendi Mutex
     accesso ai dati
     ... Take Mutex <== Bloccherà
     ...
   Fornisci dati di accesso Mutex <== Unblocks
                                  ...
                                Dai a Mutex

Semaforo binario Il semaforo
binario pone una domanda completamente diversa:

  • L'attività B è in attesa di accadere qualcosa (ad esempio un sensore è scattato).
  • Il sensore scatta e viene eseguita una routine di servizio di interruzione. Deve notificare un'attività del viaggio.
  • L'attività B deve essere eseguita e intraprendere le azioni appropriate per il viaggio del sensore. Quindi torna ad aspettare.

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

Nota che con un semaforo binario, è OK per B prendere il semaforo e A per darlo.
Ancora una volta, un semaforo binario NON protegge una risorsa dall'accesso. L'atto di dare e prendere un semaforo è fondamentalmente disaccoppiato.
In genere non ha molto senso che lo stesso compito dia e dia lo stesso semaforo binario.


12
Allora un mutex non è migliore di un semaforo binario? Dal momento che non ha senso se qualcuno rilascia un lucchetto che in realtà non tiene.
Pacerier,

111
Hanno scopi diversi. Mutex è per l'accesso esclusivo a una risorsa. Un semaforo binario dovrebbe essere usato per la sincronizzazione (es. "Hey Someone! Questo è successo!"). Il "donatore" binario notifica semplicemente a chiunque il "tiratore" che ciò che stavano aspettando è successo.
Benoit,

5
@Pacerier Stai confondendo lo scopo. Un mutex è destinato a proteggere una regione critica. Hai ragione, non ha senso usare un semaforo binario. Aggiornerò la risposta per spiegare lo scopo di ciascuno.
Benoit,

4
@Benoit Quindi possiamo dire che i mutex sono usati per l'atomicità e il semaforo binario per la prospettiva degli ordini poiché l'attività B attenderà che l'attività A segnali il rilascio del blocco intrinsecamente assicurandosi di ordinare le operazioni su una struttura di dati?
abhi,

1
@abhi Questo è un buon modo di vederlo per il Mutex. Tuttavia, a seconda del sistema operativo, è possibile avere più di un destinatario in attesa su un semaforo binario. In tal caso, solo uno dei client otterrà il sem binario. Gli altri aspetterebbero uno successivo. L'ordine di ricezione è noto o garantito? Dipende dal sistema operativo.
Benoit

446
  • Un mutex può essere rilasciato solo dal thread che lo ha acquisito .
  • Un semaforo binario può essere segnalato da qualsiasi thread (o processo).

quindi i semafori sono più adatti per alcuni problemi di sincronizzazione come produttore-consumatore.

Su Windows, i semafori binari sono più simili agli oggetti evento che ai mutex.


34
Mutex can be released only by thread that had acquired it- Ho appena provato con un semplice programma basato su pthread_mutex, un thread può sbloccare mutex bloccato nel thread principale
daisy,

15
@ warl0ck Secondo la pagina man di pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock : "Se il tipo mutex è PTHREAD_MUTEX_ERRORCHECK, allora deve essere fornito un controllo degli errori .... Se un thread tenta di sbloccare un mutex che ha non bloccato o un mutex sbloccato, deve essere restituito un errore. "
Amit

47
@ warl0ck Si prega di consultare stackoverflow.com/a/5492499/385064 Pthread' ha 3 diversi tipi di mutex: mutex veloce, mutex ricorsiva, e il controllo degli errori mutex. È stato utilizzato un mutex veloce che, per motivi di prestazioni, non verificherà questo errore. Se usi l'errore durante il controllo di mutex su Linux, scoprirai che otterrai i risultati che ti aspetti. "
FrostNovaZzz,

1
Nel nostro codice abbiamo usato mutex anche a scopi di sincronizzazione. Il thread che blocca nuovamente il mutex ha provato a bloccare il mutex, quindi passa allo stato bloccato. Ciò che abbiamo visto è che siamo in grado di sbloccare questo da un altro thread. sincronizzazione tra i due. Stiamo usando solo posix standard. Quindi la differenza principale tra mutex e semaforo binario sembra vaga.
achoora,

1
@achoora Sono d'accordo che sia sbagliato specializzare il semaforo per la sincronizzazione. In realtà tutti i mutex, i binari-semafori, le barriere e le condutture sono modelli diversi per la sincronizzazione. Nella prospettiva di progettazione, i mutex sono più simili al modello di stato in cui l'algoritmo selezionato dallo stato può cambiare lo stato. Il semaforo binario è più simile al modello di strategia in cui l'algoritmo esterno può cambiare lo stato e, infine, l'algoritmo / la strategia selezionati per l'esecuzione.
shuva,

442

L'esempio di Toilet è una piacevole analogia:

mutex:

È la chiave di una toilette. Una persona può avere la chiave - occupare la toilette - al momento. Al termine, la persona fornisce (libera) la chiave alla persona successiva nella coda.

Ufficialmente: "I mutex sono in genere utilizzati per serializzare l'accesso a una sezione di codice rientrante che non può essere eseguita contemporaneamente da più di un thread. Un oggetto mutex consente solo un thread in una sezione controllata, forzando altri thread che tentano di accedere a quella sezione in attesa 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 identiche gratuite della toilette. Ad esempio, supponiamo di avere quattro servizi igienici con chiavi e serrature identiche. Il conteggio dei semafori - il conteggio delle chiavi - è impostato su 4 all'inizio (tutti e quattro i servizi igienici sono gratuiti), quindi il valore del conteggio viene ridotto man mano che le persone entrano. Se tutti i servizi igienici sono pieni, vale a dire. non sono rimasti tasti liberi, il conteggio dei semafori è 0. Ora, quando l'eq. una persona esce dal gabinetto, il semaforo viene aumentato a 1 (una chiave libera) e assegnato alla persona successiva nella 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 (decrementando il semaforo) e possono segnalare che hanno finito di usare la risorsa (incrementando il semaforo). " Rif: Symbian Developer Library


234
... ma questo riguarda il mutex e il conteggio dei semafori. La domanda è stata posta sul binario.
Roman Nikitchenko,

24
Mentre quello che dice David è corretto, ma NON è la risposta alla domanda posta. La risposta di Mladen Jankovic è la risposta alla domanda posta, in cui si sottolinea la differenza tra "semaforo binario" e "mutex".
Ajeet Ganga,

13
Sfortunatamente, questa risposta errata ha più voti della migliore risposta di @Benoit
NeonGlow

6
Questa risposta è fuorviante. Avrebbe dovuto confrontarsi solo con il semaforo binario.
Hemanth,

3
Ciò dimostra anche un problema con l'utilizzo di un semaforo di conteggio per proteggere una risorsa condivisa: se le chiavi sono effettivamente identiche e un gabinetto viene sbloccato utilizzando una chiave e non esiste un altro meccanismo per distribuire l'utilizzo del cubicolo, quindi: (1) il primo l'utente sblocca, entra e inizia a utilizzare il primo cubicolo. (2) l'utente successivo sblocca, entra e inizia a usare il primo cubicolo ...
Technophile

151

Bei articoli sull'argomento:

Dalla parte 2:

Il mutex è simile ai principi del semaforo binario con una differenza significativa: il principio di proprietà. La proprietà è il semplice concetto che quando un'attività blocca (acquisisce) solo un mutex può sbloccarlo (rilasciarlo). Se un'attività tenta di sbloccare un mutex che non ha bloccato (quindi non possiede), si verifica una condizione di errore e, soprattutto, il mutex non è sbloccato. Se l'oggetto di esclusione reciproca non ha proprietà, quindi, indipendentemente da come viene chiamato, non è un mutex.


Grazie per il link, le spiegazioni ci sono eccellenti. Il collegamento è stato modificato: feabhas.com/blog/2009/09/… (Usa <Prec. E Succ.> Per navigare verso gli altri due articoli.
Aaron H.

@Aaron Ho corretto i collegamenti
giudice Maygarden il

Nota: la mancanza di proprietà impedisce anche al sistema operativo di aggirare l'inversione di priorità. Per questo motivo, generalmente utilizzo variabili di condizione anziché semafori per architetture di produttori / consumatori.
kgriffs

1
+1 per gli eccellenti collegamenti agli articoli. Il miglior articolo che spiega semaforo e mutex con "che cosa è" e "che cosa fa" computing.llnl.gov/tutorials/pthreads Ho usato questo articolo come riferimento dietro le quinte, che tecnicamente spiega tutto su mutex / condizionali e altri costrutti costruiti sulla loro sommità come semaforo / barriera / lettore-scrittore, ma da nessuna parte espliciti e concisi sui problemi affrontati con i costrutti. In breve è riferimento. :)
Ajeet Ganga,

più facilmente comprensibile rispetto alle altre risposte.
BinaryTreeee,

101

Poiché nessuna delle risposte precedenti cancella la confusione, eccone una che ha chiarito la mia confusione.

A rigor di termini, un mutex è un meccanismo di blocco utilizzato per sincronizzare l'accesso a una risorsa. Solo un task (può essere un thread o un processo basato sull'astrazione del sistema operativo) può acquisire il mutex. Significa che ci sarà la proprietà associata a mutex e solo il proprietario può rilasciare il blocco (mutex).

Il semaforo è un meccanismo di segnalazione (tipo di segnale "Ho finito, puoi continuare"). Ad esempio, se stai ascoltando brani (assumilo come un'attività) sul tuo cellulare e allo stesso tempo il tuo amico ti ha chiamato, verrà attivato un interrupt su cui una routine di servizio di interruzione (ISR) segnalerà l'attività di elaborazione delle chiamate per riattivare .

Fonte: http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

La loro semantica di sincronizzazione è molto diversa:

  • i mutex consentono la serializzazione dell'accesso a una determinata risorsa, ovvero più thread attendono un blocco, uno alla volta e, come detto in precedenza, il thread possiede il blocco fino a quando non viene eseguito: solo questo particolare thread può sbloccarlo.
  • un semaforo binario è un contatore con il valore 0 e 1: un'operazione di blocco su di esso fino qualsiasi operazione fa un sem_post. Il semaforo pubblicizza la disponibilità di una risorsa e fornisce il meccanismo per attendere fino a quando viene segnalato come disponibile.

Come tale si può vedere un mutex come un token passato da un compito all'altro e un semaforo come semaforo rosso ( segnala a qualcuno che può procedere).


23

A livello teorico, non sono diversi semanticamente. Puoi implementare un mutex usando i semafori o viceversa (vedi qui per un esempio). In pratica, l'implementazione è diversa e offrono servizi leggermente diversi.

La differenza pratica (in termini di servizi di sistema che li circondano) è che l'implementazione di un mutex è finalizzata ad essere un meccanismo di sincronizzazione più leggero. In oracolo, i mutex sono noti come chiavistelli e i semafori sono noti come attese .

Al livello più basso, usano una sorta di test atomico e impostano il meccanismo. Questo legge il valore corrente di una posizione di memoria, calcola una sorta di condizionale e scrive un valore in quella posizione in una singola istruzione che non può essere interrotta . Ciò significa che puoi acquisire un mutex e testare per vedere se qualcun altro lo ha avuto prima di te.

Una tipica implementazione di mutex ha un processo o thread che esegue l'istruzione test-and-set e valuta se qualcos'altro ha impostato il mutex. Un punto chiave qui è che non c'è interazione con lo scheduler , quindi non abbiamo idea (e non ci interessa) chi ha impostato il blocco. Quindi rinunciamo alla nostra fascia oraria e la riproviamo quando l'attività viene riprogrammata o eseguiamo un blocco di spin . Uno spin lock è un algoritmo come:

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

Quando abbiamo finito di eseguire il nostro codice protetto (noto come sezione critica ) abbiamo semplicemente impostato il valore di mutex su zero o qualunque cosa significhi "cancella". Se più attività stanno tentando di acquisire il mutex, l'attività successiva che viene pianificata dopo il rilascio del mutex avrà accesso alla risorsa. In genere si utilizzano i mutex per controllare una risorsa sincronizzata in cui l'accesso esclusivo è necessario solo per periodi di tempo molto brevi, normalmente per effettuare un aggiornamento di una struttura di dati condivisa.

Un semaforo è una struttura di dati sincronizzata (in genere utilizzando un mutex) che ha un conteggio e alcuni wrapper di chiamate di sistema che interagiscono con lo scheduler in modo leggermente più approfondito rispetto alle librerie di mutex. I semafori vengono incrementati e decrementati e utilizzati per bloccare le attività fino a quando qualcos'altro è pronto. Vedi Problema produttore / consumatore per un semplice esempio di questo. I semafori sono inizializzati su un certo valore: un semaforo binario è solo un caso speciale in cui il semaforo è inizializzato su 1. La pubblicazione su un semaforo ha l'effetto di svegliare un processo di attesa.

Un algoritmo di semaforo di base assomiglia a:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

Nel caso di un semaforo binario la principale differenza pratica tra i due è la natura dei servizi di sistema che circondano la struttura dati effettiva.

EDIT: Come ha giustamente sottolineato Evan, gli spinlock rallenteranno un singolo processore. Utilizzeresti uno spinlock su una scatola multi-processore perché su un singolo processore il processo che tiene il mutex non lo ripristinerà mai mentre è in esecuzione un'altra attività. Gli spinlock sono utili solo su architetture multiprocessore.


1
Non credo sia pratica comune implementare un mutex con spinlock. Su una macchina Uni-proc questo sarebbe assolutamente terribile per le prestazioni.
Evan Teran,

Normalmente useresti gli spinlock solo su sistemi multiprocessore.
ConcernedOfTunbridgeWells il

Anche su SMP, dopo aver girato alcune volte, si ritorna alla modalità sleep / wake assistita dal sistema operativo. (ad es. la futexchiamata di sistema Linux esiste per aiutare le implementazioni di mutex / semaphore dello spazio utente a bassa latenza. en.wikipedia.org/wiki/Futex ) Nel percorso rapido senza contese, o se la risorsa diventa presto disponibile, non si ha mai il sovraccarico di una chiamata di sistema. Ma non passi più di qualche micro-secondo in attesa (rotazione). L'ottimizzazione dei parametri di backoff spin-loop e wait dipende ovviamente dall'hardware e dal carico di lavoro, ma la libreria standard di solito ha scelte ragionevoli.
Peter Cordes,

19

Sebbene mutex e semafori siano usati come primitive di sincronizzazione, c'è una grande differenza tra loro. Nel caso del mutex, solo il thread che ha bloccato o acquisito il mutex può sbloccarlo. Nel caso di un semaforo, un thread in attesa su un semaforo può essere segnalato da un thread diverso. Alcuni sistemi operativi supportano l'utilizzo di mutex e semafori tra i processi. In genere l'utilizzo sta creando nella memoria condivisa.


"può essere segnalato da un thread diverso" cosa significa fare un esempio.
Myanju,

15

Mutex: supponiamo di avere un thread di sezione critica T1 che vuole accedervi, quindi segue i passaggi seguenti. T1:

  1. Serratura
  2. Usa la sezione critica
  3. Sbloccare

Semaforo binario: funziona in base alla segnalazione di attesa e segnale. wait (s) diminuisce il valore "s" di uno di solito il valore "s" viene inizializzato con il valore "1", il segnale (i) aumenta il valore "s" di uno. se il valore "s" è 1 significa che nessuno sta usando la sezione critica, quando il valore è 0 significa che la sezione critica è in uso. supponiamo che il thread T2 stia utilizzando la sezione critica, quindi segue i passaggi seguenti. T2:

  1. wait (s) // inizialmente il valore è uno dopo aver chiamato wait il suo valore è diminuito di uno, cioè 0
  2. Usa la sezione critica
  3. segnale / i // ora il valore di s viene aumentato e diventa 1

La differenza principale tra Mutex e il semaforo binario è in Mutext se il thread blocca la sezione critica, quindi deve sbloccare la sezione critica nessun altro thread può sbloccarlo, ma nel caso del semaforo binario se un thread blocca la sezione critica usando la funzione wait (s), quindi il valore di s diventa "0" e nessuno può accedervi fino a quando il valore di "s" diventa 1, ma supponiamo che alcuni altri segnali di chiamata di thread, quindi il valore di "s" diventi 1 e consenta ad altre funzioni di utilizzare la sezione critica. quindi nel thread semaforo binario non ha proprietà.


12

Su Windows, ci sono due differenze tra mutex e semafori binari:

  1. Un mutex può essere rilasciato solo dal thread che ha la proprietà, ovvero il thread che precedentemente chiamava la funzione Wait (o che ha assunto la proprietà durante la creazione). Un semaforo può essere rilasciato da qualsiasi thread.

  2. Un thread può chiamare ripetutamente una funzione di attesa su un mutex senza bloccare. Tuttavia, se si chiama due volte una funzione di attesa su un semaforo binario senza rilasciare il semaforo in mezzo, il thread si bloccherà.


4
Buona risposta. Nel # 2 stai descrivendo un mutex ricorsivo - non tutti i mutex sono necessariamente ricorsivi. Ad esempio, cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

Ovviamente usi mutex per bloccare un dato in un thread a cui accede contemporaneamente un altro thread. Supponiamo che tu abbia appena chiamato lock()e in procinto di accedere ai dati. Ciò significa che non ti aspetti che nessun altro thread (o un'altra istanza dello stesso thread-code) acceda agli stessi dati bloccati dallo stesso mutex. Cioè, se è lo stesso thread-code che viene eseguito su un'istanza di thread diversa, preme il lucchetto, quindi illock()dovrebbe bloccare il flusso di controllo lì. Questo vale per un thread che utilizza un thread-code diverso, che accede anche agli stessi dati e che è anche bloccato dallo stesso mutex. In questo caso, stai ancora accedendo ai dati e potresti impiegare, diciamo, altri 15 secondi per raggiungere lo sblocco mutex (in modo che l'altro thread che viene bloccato nel blocco mutex si sblocchi e consenta al controllo di accedere ai dati). Ad ogni costo consenti a un altro thread di sbloccare lo stesso mutex e, a sua volta, consenti al thread che è già in attesa (blocco) nel blocco mutex di sbloccare e accedere ai dati? Spero che tu abbia quello che sto dicendo qui? Secondo la definizione universale concordata !,

  • con "mutex" questo non può succedere. Nessun altro thread può sbloccare il blocco nel thread
  • con "binary-semaphore" questo può accadere. Qualsiasi altro thread può sbloccare il blocco nel thread

Quindi, se sei molto preciso sull'uso del semaforo binario invece del mutex, allora dovresti stare molto attento a "scopare" i blocchi e gli sblocchi. Voglio dire che ogni flusso di controllo che colpisce ogni blocco dovrebbe colpire una chiamata di sblocco, inoltre non dovrebbe esserci alcun "primo sblocco", piuttosto dovrebbe essere sempre "primo blocco".


10

I mutex sono usati per "Meccanismi di bloccaggio". un processo alla volta può utilizzare una risorsa condivisa

mentre

I semafori vengono utilizzati per "meccanismi di segnalazione" come "I am done, now can continue"


9

Mito:

Un paio di articoli affermano che "il semaforo binario e il mutex sono uguali" o "Il semaforo con valore 1 è mutex" ma la differenza di base è che il mutex può essere rilasciato solo dal thread che lo ha acquisito, mentre è possibile segnalare il semaforo da qualsiasi altro thread

Punti chiave:

• Un thread può acquisire più di un blocco (Mutex).

• Un mutex può essere bloccato più di una volta solo se è un mutex ricorsivo, qui bloccare e sbloccare per mutex dovrebbe essere lo stesso

• Se un thread che aveva già bloccato un mutex, tenta di bloccare nuovamente il mutex, entrerà nella lista di attesa di quel mutex, con conseguente deadlock.

• Semaforo binario e mutex sono simili ma non uguali.

• Il mutex è un'operazione costosa a causa dei protocolli di protezione ad esso associati.

• L'obiettivo principale di mutex è raggiungere l'accesso atomico o bloccare la risorsa


8

Un Mutex controlla l'accesso a una singola risorsa condivisa. Fornisce operazioni per acquisire () l' accesso a tale risorsa e rilasciarlo () al termine.

Un semaforo controlla l'accesso a un pool condiviso di risorse. Fornisce operazioni a Wait () fino a quando una delle risorse nel pool non diventa disponibile e Signal () quando viene restituito al pool.

Quando il numero di risorse che un semaforo protegge è maggiore di 1, viene chiamato semaforo di conteggio . Quando controlla una risorsa, viene chiamato semaforo booleano . Un semaforo booleano è equivalente a un mutex.

Quindi un semaforo è un'astrazione di livello superiore rispetto al mutex. Un Mutex può essere implementato usando un semaforo ma non viceversa.


6

La domanda modificata è: qual è la differenza tra A mutex e un semaforo "binario" in "Linux"?

Risposta: Di seguito sono riportate le differenze: i) Ambito: l'ambito di mutex è all'interno di uno spazio degli indirizzi di processo che lo ha creato e viene utilizzato per la sincronizzazione dei thread. Considerando che il semaforo può essere utilizzato attraverso lo spazio di processo e quindi può essere utilizzato per la sincronizzazione tra processi.

ii) Il mutex è leggero e più veloce del semaforo. Futex è ancora più veloce.

iii) Il mutex può essere acquisito con successo dallo stesso thread più volte, a condizione che venga rilasciato lo stesso numero di volte. L'altro thread che tenta di acquisire verrà bloccato. Mentre in caso di semaforo se lo stesso processo tenta di acquisirlo di nuovo, si blocca poiché può essere acquisito una sola volta.


i) Sbagliato. ii) Fonte? iii) Dipende.
curiousguy,

6

Diff tra Binary Semaphore e Mutex: PROPRIETÀ: I semafori possono essere segnalati (pubblicati) anche da un proprietario non corrente. Significa che puoi semplicemente postare da qualsiasi altra discussione, anche se non sei il proprietario.

Il semaforo è una proprietà pubblica in corso, può essere semplicemente pubblicato da un thread non proprietario. Si prega di contrassegnare questa differenza in lettere grassetto, significa molto.


5

I mutex lavorano per bloccare la regione critica, ma Semaphore lavora per conto.



4

A parte il fatto che i mutex hanno un proprietario, i due oggetti possono essere ottimizzati per un uso diverso. I mutex sono progettati per essere tenuti solo per un breve periodo; la violazione di ciò può causare scarse prestazioni e programmazione sleale. Ad esempio, un thread in esecuzione può essere autorizzato ad acquisire un mutex, anche se un altro thread è già bloccato su di esso. I semafori possono fornire più equità o l'equità può essere forzata utilizzando diverse variabili di condizione.


In quali casi specifici è garantita l'equità per i semafori ma non per i mutex?
curiousguy,

1
POSIX ha requisiti specifici che filo si desidera attivare da sem_post()per SCHED_FIFOe SCHED_RR(entrambi di questi non sono predefinita): la massima priorità filo, e se ci sono molteplici con la stessa priorità, il filo che è la più lunga attesa. OpenSolaris segue questa regola FIFO in una certa misura anche per la normale programmazione. Per glibc e FreeBSD, sbloccare un semplice mutex (ovvero non proteggere la priorità o ereditare la priorità) e pubblicare un semaforo sono sostanzialmente gli stessi, contrassegnando l'oggetto come sbloccato e quindi, se potrebbero esserci dei thread in attesa, chiamando il kernel per svegliarne uno.
jilles,

4

In Windows la differenza è la seguente. MUTEX: il processo che esegue correttamente wait deve eseguire un segnale e viceversa. SEMAFORI BINARI: processi diversi possono eseguire operazioni di attesa o segnale su un semaforo.


4

Mentre un semaforo binario può essere usato come mutex, un mutex è un caso d'uso più specifico, in quanto si suppone che solo il processo che ha bloccato il mutex lo sblocchi. Questo vincolo di proprietà consente di fornire protezione contro:

  • Rilascio accidentale
  • Deadlock ricorsivo
  • Task Death Deadlock

Questi vincoli non sono sempre presenti perché degradano la velocità. Durante lo sviluppo del codice, è possibile abilitare temporaneamente questi controlli.

ad esempio puoi abilitare l'attributo Controllo errori nel tuo mutex. Errore durante il controllo del ritorno dei mutexEDEADLK se si tenta di bloccare lo stesso due volte e EPERMse si sblocca un mutex non tuo.

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

Una volta inizializzati, possiamo inserire questi controlli nel nostro codice in questo modo:

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");

4

Il concetto mi è stato chiaro dopo aver esaminato i post precedenti. Ma c'erano alcune domande persistenti. Quindi, ho scritto questo piccolo pezzo di codice.

Quando proviamo a dare un semaforo senza prenderlo, passa attraverso. Ma quando provi a dare un mutex senza prenderlo, fallisce. Ho provato questo su una piattaforma Windows. Abilitare USE_MUTEX per eseguire lo stesso codice utilizzando un MUTEX.

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}

Il fatto stesso che il semaforo ti permetta di segnalare "è fatto usando una risorsa", anche se non ha mai posseduto la risorsa, mi fa pensare che ci sia un accoppiamento molto libero tra possedere e segnalare nel caso dei semafori.


Se leggi le altre risposte, è chiaro che il concetto di "proprietà" ha senso solo con i mutex, non con i semafori. I semafori potrebbero essere utilizzati per cose come un thread che consente ad altri thread di sapere che l'elaborazione di un blocco di dati viene eseguita; risultati pronti per la lettura.
Peter Cordes,

2

Il mutex è usato per proteggere il codice sensibile e i dati, il semaforo è usato per la sincronizzazione. Puoi anche avere un uso pratico con proteggere il codice sensibile, ma potrebbe esserci un rischio che rilasci la protezione dall'altro thread tramite l'operazione V. la differenza tra bi-semaforo e mutex è la proprietà.Ad esempio per servizi igienici, Mutex è come se si potesse entrare nel bagno e chiudere a chiave la porta, nessun altro può entrare fino a quando l'uomo non esce, il bi-semaforo è come se si potesse entrare il bagno e chiudere a chiave la porta, ma qualcun altro potrebbe entrare chiedendo all'amministratore di aprire la porta, è ridicolo.


2

mutex

I mutex vengono in genere utilizzati per serializzare l'accesso a una sezione di codice rientrante che non può essere eseguita contemporaneamente da più di un thread. Un oggetto mutex consente solo un thread in una sezione controllata, forzando altri thread che tentano di accedere a quella sezione di attendere fino a quando il primo thread è uscito da quella sezione. L'uso corretto di un mutex è di proteggere una risorsa condivisa può avere un pericolo effetto collaterale indesiderato. Qualsiasi due attività RTOS che operano a priorità diverse e si coordinano tramite un mutex, creano l'opportunità per l'inversione di priorità . Mutex funziona nello spazio utente .

Semaforo

Il semaforo è un meccanismo di segnalazione. Il semaforo limita il numero di utenti simultanei di una risorsa condivisa fino a un numero massimo. I thread possono richiedere l'accesso alla risorsa (decrementando il semaforo) e possono segnalare che hanno finito di usare la risorsa (incrementando il semaforo). Consente al numero di thread di accedere alle risorse condivise. L'uso corretto di un semaforo è per la segnalazione da un'attività all'altra. I metaforismi possono anche essere utilizzati per segnalare da una routine di servizio di interruzione (ISR) a un'attività. La segnalazione di un semaforo è un comportamento RTOS non bloccante e quindi ISR ​​sicuro. Perché questa tecnica elimina la necessità soggetta a errori di disabilitare gli interrupt a livello di attività. Questo funziona nello spazio del kernel .


1

La risposta potrebbe dipendere dal sistema operativo di destinazione. Ad esempio, almeno un'implementazione RTOS che conosco consentirà più operazioni "get" sequenziali su un singolo mutex del sistema operativo, purché provengano tutti dallo stesso contesto di thread. I get multipli devono essere sostituiti da un numero uguale di put prima che un altro thread possa ottenere il mutex. Ciò differisce dai semafori binari, per i quali è consentito un solo get alla volta, indipendentemente dal contesto del thread.

L'idea alla base di questo tipo di mutex è quella di proteggere un oggetto consentendo a un solo contesto di modificare i dati alla volta. Anche se il thread ottiene il mutex e quindi chiama una funzione che modifica ulteriormente l'oggetto (e ottiene / mette il mutex del protettore attorno alle proprie operazioni), le operazioni dovrebbero essere comunque sicure perché avvengono tutte sotto un singolo thread.

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

Naturalmente, quando si utilizza questa funzione, è necessario essere sicuri che tutti gli accessi all'interno di un singolo thread siano davvero sicuri!

Non sono sicuro di quanto sia comune questo approccio o se si applica al di fuori dei sistemi con cui ho familiarità. Per un esempio di questo tipo di mutex, vedere ThreadX RTOS.


2
Il tipo di mutex di cui stai parlando si chiama "mutex ricorsivo" e dovrebbe essere evitato poiché sono lenti e tendono a promuovere un cattivo design: (vedi David Butenhof: zaval.org/resources/library/butenhof1.html )
gaspard

Concordato. Su questo particolare sistema operativo, utilizzo il servizio mutex in cui desidero chiarire che il codice è per "l'esclusione reciproca" e non il conteggio dei riferimenti, ma non uso la funzione ricorsiva per paura di un brutto svolgersi. Tuttavia, nel contesto della domanda, questa è una differenza importante tra un "mutex" e un "semaforo binario".
Casey Barker,

1

I mutex hanno proprietà, a differenza dei semafori. Sebbene qualsiasi thread, nell'ambito di un mutex, possa ottenere un mutex sbloccato e bloccare l'accesso alla stessa sezione critica di codice, solo il thread che ha bloccato un mutex dovrebbe sbloccarlo .


che cos'è la proprietà? Intendi che il contesto che acquisisce il mutex può solo annullarlo. ??
Raulp,

1

Come molti hanno menzionato qui, un mutex viene utilizzato per proteggere un pezzo di codice critico (sezione critica di AKA.) Acquisirai il mutex (blocco), entrerai nella sezione critica e rilascerai il mutex (sblocco) tutto nello stesso thread .

Durante l'utilizzo di un semaforo, è possibile fare in modo che un thread attenda un semaforo (ad esempio thread A), fino a quando un altro thread (ad esempio thread B) completa qualsiasi attività, quindi imposta il semaforo per il thread A in modo da interrompere l'attesa e continuare l'attività.


1

Soluzione migliore

L'unica differenza è

1.Mutex -> blocco e sblocco sono di proprietà di un thread che blocca il mutex.

2.Semaphore -> Nessuna proprietà, ad es. se un thread chiama semwait (s) qualsiasi altro thread può chiamare sempost (s) per rimuovere il blocco.


1

MUTEX

Fino a poco tempo fa, l'unico blocco di sospensione nel kernel era il semaforo. La maggior parte degli utenti di semafori ha istanziato un semaforo con un conteggio di uno e li ha trattati come un blocco di esclusione reciproca, una versione dormiente del blocco di spin. Sfortunatamente, i semafori sono piuttosto generici e non impongono alcun vincolo di utilizzo. Questo li rende utili per la gestione dell'accesso esclusivo in situazioni oscure, come danze complicate tra il kernel e lo spazio utente. Ma significa anche che è più difficile eseguire un blocco più semplice e la mancanza di regole applicate rende impossibile qualsiasi tipo di debug automatico o applicazione di vincoli. Alla ricerca di un semplice blocco per dormire, gli sviluppatori del kernel hanno introdotto il mutex. Sì, come ormai sei abituato, è un nome confuso. Chiariamo. Il termine "mutex" è un nome generico che si riferisce a qualsiasi blocco del sonno che impone l'esclusione reciproca, come un semaforo con un conteggio di utilizzo pari a uno. Nei recenti kernel di Linux, il nome proprio "mutex" è ora anche un tipo specifico di blocco del sonno che implementa l'esclusione reciproca, ovvero un mutex è un mutex.

La semplicità e l'efficienza del mutex derivano dai vincoli aggiuntivi che impone ai suoi utenti oltre a ciò che il semaforo richiede. A differenza di un semaforo, che implementa il comportamento più elementare in conformità con il progetto originale di Dijkstra, il mutex ha un caso d'uso più rigoroso e più stretto: n Solo un compito può contenere il mutex alla volta. Cioè, il conteggio di utilizzo su un mutex è sempre uno.

  1. Chiunque abbia bloccato un mutex deve sbloccarlo. Cioè, non è possibile bloccare un mutex in un contesto e quindi sbloccarlo in un altro. Ciò significa che il mutex non è adatto per sincronizzazioni più complicate tra kernel e spazio utente. La maggior parte dei casi d'uso, tuttavia, blocca e sblocca in modo pulito dallo stesso contesto.
  2. Non sono consentiti blocchi e sblocchi ricorsivi. Cioè, non puoi acquisire ricorsivamente lo stesso mutex e non puoi sbloccare un mutex sbloccato.
  3. Un processo non può uscire mentre si tiene un mutex.
  4. Un mutex non può essere acquisito da un gestore di interrupt o metà inferiore, anche con mutex_trylock ().
  5. Un mutex può essere gestito solo tramite l'API ufficiale: deve essere inizializzato tramite i metodi descritti in questa sezione e non può essere copiato, inizializzato a mano o reinizializzato.

[1] Sviluppo del kernel Linux, terza edizione Robert Love


1

Penso che la maggior parte delle risposte qui siano state confuse, specialmente quelle che affermano che il mutex può essere rilasciato solo dal processo che lo contiene, ma il semaforo può essere segnalato da qualsiasi processo. La riga sopra è piuttosto vaga in termini di semaforo. Per capire dovremmo sapere che esistono due tipi di semafori: uno si chiama conteggio dei semafori e l'altro è chiamato un semaforo binario. Nel conteggio dei semafori gestisce l'accesso a n numero di risorse in cui n può essere definito prima dell'uso. Ogni semaforo ha una variabile count, che mantiene il conteggio del numero di risorse in uso, inizialmente è impostato su n. Ogni processo che desidera utilizzare una risorsa esegue un'operazione wait () sul semaforo (diminuendo così il conteggio). Quando un processo rilascia una risorsa, esegue un'operazione release () (incrementando il conteggio). Quando il conteggio diventa 0, tutte le risorse vengono utilizzate. Dopodiché, il processo attende che il conteggio diventi più di 0. Ora ecco il fermo solo il processo che contiene la risorsa può aumentare il conteggio Nessun altro processo può aumentare il conteggio solo i processi che detengono una risorsa possono aumentare il conteggio e il processo l'attesa del semaforo verifica nuovamente e quando vede la risorsa disponibile diminuisce nuovamente il conteggio. Quindi, in termini di semaforo binario, solo il processo che contiene il semaforo può aumentare il conteggio e il conteggio rimane zero fino a quando non smette di usare il semaforo e aumenta il conteggio e altri processi hanno la possibilità di accedere al semaforo. Ora ecco il fermo solo il processo che contiene la risorsa può aumentare il conteggio nessun altro processo può aumentare il conteggio solo i processi che detengono una risorsa possono aumentare il conteggio e il processo in attesa del semaforo controlla di nuovo e quando vede la risorsa disponibile riduce di nuovo il conteggio. Quindi, in termini di semaforo binario, solo il processo che contiene il semaforo può aumentare il conteggio e il conteggio rimane zero fino a quando non smette di usare il semaforo e aumenta il conteggio e altri processi hanno la possibilità di accedere al semaforo. Ora ecco il fermo solo il processo che contiene la risorsa può aumentare il conteggio nessun altro processo può aumentare il conteggio solo i processi che detengono una risorsa possono aumentare il conteggio e il processo in attesa del semaforo controlla di nuovo e quando vede la risorsa disponibile riduce di nuovo il conteggio. Quindi, in termini di semaforo binario, solo il processo che contiene il semaforo può aumentare il conteggio e il conteggio rimane zero fino a quando non smette di usare il semaforo e aumenta il conteggio e altri processi hanno la possibilità di accedere al semaforo.

La differenza principale tra semaforo binario e mutex è che il semaforo è un meccanismo di segnalazione e il mutex è un meccanismo di blocco, ma il semaforo binario sembra funzionare come un mutex che crea confusione, ma entrambi sono concetti diversi adatti a diversi tipi di lavoro.

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.