C'è qualche differenza tra un semaforo binario e un mutex o sono essenzialmente gli stessi?
C'è qualche differenza tra un semaforo binario e un mutex o sono essenzialmente gli stessi?
Risposte:
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:
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.
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.
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
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
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.
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 .
La loro semantica di sincronizzazione è molto diversa:
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).
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.
futex
chiamata 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.
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.
Mutex: supponiamo di avere un thread di sezione critica T1 che vuole accedervi, quindi segue i passaggi seguenti. T1:
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:
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à.
Su Windows, ci sono due differenze tra mutex e semafori binari:
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.
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à.
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 !,
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".
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"
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
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.
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.
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.
I mutex lavorano per bloccare la regione critica, ma Semaphore lavora per conto.
http://www.geeksforgeeks.org/archives/9102 discute in dettaglio.
Mutex
è il meccanismo di blocco utilizzato per sincronizzare l'accesso a una risorsa.
Semaphore
è un meccanismo di segnalazione.
Sta al programmatore se vuole usare il semaforo binario al posto del mutex.
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.
sem_post()
per SCHED_FIFO
e 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.
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.
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:
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 EPERM
se 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");
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.
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.
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 .
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.
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 .
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à.
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.
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] Sviluppo del kernel Linux, terza edizione Robert Love
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.