Cos’è un mutex?

Un mutex è un concetto di programmazione che viene spesso utilizzato per risolvere problemi di multi-threading. La mia domanda alla comunità:

Cos’è un mutex e come lo usi?

    Quando ho una grande discussione accesa sul lavoro, uso un pollo di gomma che tengo sulla mia scrivania proprio per queste occasioni. La persona che detiene il pollo è l’unica persona a cui è permesso parlare. Se non trattieni il pollo non puoi parlare. Puoi solo indicare che vuoi il pollo e aspettare finché non lo ottieni prima di parlare. Una volta che hai finito di parlare, puoi restituire il pollo al moderatore che lo consegnerà alla persona successiva per parlare. Ciò garantisce che le persone non parlino l’una sull’altra e abbiano anche il proprio spazio per parlare.

    Sostituisci Chicken with Mutex e person with thread e in pratica hai il concetto di mutex.

    Certo, non esiste un mutex di gomma. Solo pollo di gomma. I miei gatti una volta avevano un topo di gomma, ma lo mangiarono.

    Ovviamente, prima di usare il pollo di gomma, è necessario chiedersi se effettivamente occorrono 5 persone in una stanza e non sarebbe solo più facile con una persona nella stanza da sola a fare tutto il lavoro. In realtà, questo è solo un’estensione dell’analogia, ma tu hai l’idea.

    Un mutex è una bandiera che si escludono a vicenda. Funziona come un custode di una sezione di codice che consente di inserire un thread e bloccare l’accesso a tutti gli altri. Ciò garantisce che il codice che viene controllato venga colpito da un singolo thread alla volta. Assicurati di rilasciare il mutex quando hai finito. 🙂

    Esclusione reciproca. Ecco la voce di Wikipedia su di esso:

    http://en.wikipedia.org/wiki/Mutual_exclusion

    Il punto di un mutex è sincronizzare due thread. Quando si hanno due thread che tentano di accedere a una singola risorsa, lo schema generale prevede che il primo blocco di codice che tenta l’accesso imposti il ​​mutex prima di immettere il codice. Quando il secondo blocco di codice tenta di accedere, vede che il mutex è impostato e attende fino al completamento del primo blocco di codice (e distriggers il mutex), quindi continua.

    I dettagli specifici di come questo è realizzato ovviamente varia notevolmente dal linguaggio di programmazione.

    Quando si ha un’applicazione multi-thread, i thread diversi a volte condividono una risorsa comune, come una variabile o simile. Spesso non è ansible accedere a questa fonte condivisa allo stesso tempo, quindi è necessario un costrutto per garantire che solo un thread utilizzi tale risorsa alla volta.

    Il concetto è chiamato “mutua esclusione” (breve Mutex) ed è un modo per garantire che solo una discussione sia consentita all’interno di quell’area, usando quella risorsa ecc.

    Come usarli è un linguaggio specifico, ma è spesso (se non sempre) basato su un mutex del sistema operativo.

    Alcuni linguaggi non hanno bisogno di questo costrutto, a causa del paradigma, ad esempio la programmazione funzionale (Haskell, ML sono buoni esempi).

    Ora vai a chiedere a Google come usarli! 🙂

    In C #, il mutex comune utilizzato è il monitor . Il tipo è ‘ System.Threading.Monitor ‘. Può anche essere usato implicitamente tramite l’istruzione ‘ lock (Object) ‘. Un esempio del suo utilizzo è quando si costruisce una class Singleton.

    private static readonly Object instanceLock = new Object(); private static MySingleton instance; public static MySingleton Instance { lock(instanceLock) { if(instance == null) { instance = new MySingleton(); } return instance; } } 

    L’istruzione di blocco che utilizza l’object lock privato crea una sezione critica. Richiedere ad ogni thread di attendere fino al termine del precedente. Il primo thread entrerà nella sezione e inizializzerà l’istanza. Il secondo thread attenderà, entrerà nella sezione e otterrà l’istanza inizializzata.

    Qualsiasi tipo di sincronizzazione di un membro statico può utilizzare l’istruzione di blocco in modo simile.

    Per comprendere MUTEX in un primo momento è necessario sapere qual è la “condizione di competizione” e solo allora capirai perché è necessario MUTEX. Supponiamo di avere un programma multi-threading e di avere due thread. Ora hai un lavoro nella coda dei lavori. Il primo thread controllerà la coda dei lavori e dopo aver trovato il lavoro inizierà l’esecuzione. Il secondo thread controllerà anche la coda dei lavori e scoprirà che c’è un lavoro in coda. Quindi, assegnerà anche lo stesso puntatore del lavoro. Quindi, ora cosa succede, entrambi i thread stanno eseguendo lo stesso lavoro. Ciò causerà un errore di segmentazione. Questo è l’esempio di una condizione di gara.

    La soluzione a questo problema è MUTEX. MUTEX è un tipo di blocco che blocca un thread alla volta. Se un altro thread vuole bloccarlo, il thread viene semplicemente bloccato.

    L’argomento MUTEX in questo link di file pdf vale davvero la pena leggerlo.

    I mutex sono utili in situazioni in cui è necessario imporre l’accesso esclusivo a una risorsa attraverso più processi, in cui un blocco regolare non è d’aiuto poiché funziona solo attraverso i thread.

    Ci sono alcune grandi risposte qui, ecco un’altra grande analogia per spiegare cosa è il mutex :

    Considera il bagno singolo con una chiave . Quando qualcuno entra, prende la chiave e il bagno è occupato . Se qualcun altro ha bisogno di usare il bagno, è necessario attendere in coda . Quando la persona in bagno ha finito , passa la chiave alla prossima persona in coda. Ha senso, giusto?

    Converti il bagno della storia in una risorsa condivisa e la chiave di un mutex . Portare la chiave in bagno (acquisire un lucchetto) ti consente di usarlo. Se non è presente alcuna chiave (il blocco è bloccato) è necessario attendere. Quando la chiave viene restituita dalla persona ( rilascia il lucchetto ), sei libero di acquisirla ora.

    Cos’è un Mutex ?

    Il mutex (in effetti, il termine mutex è l’abbreviazione di mutua esclusione) noto anche come spinlock è lo strumento di sincronizzazione più semplice che viene utilizzato per proteggere le regioni critiche e quindi prevenire le condizioni di gara. Questo thread deve acquisire un blocco prima di entrare in una sezione critica (nella sezione critica multi thread condividono una variabile comune, aggiornando una tabella, scrivendo un file e così via), rilascia il lock quando lascia la sezione critica.

    Che cos’è una condizione di gara ?

    Una condizione di competizione si verifica quando due o più thread possono accedere ai dati condivisi e cercano di cambiarli contemporaneamente. Poiché l’algoritmo di pianificazione dei thread può scambiare tra thread in qualsiasi momento, non si conosce l’ordine in cui i thread tenteranno di accedere ai dati condivisi. Pertanto, il risultato della modifica dei dati dipende dall’algoritmo di scheduling del thread, ovvero entrambi i thread sono “racing” per accedere / modificare i dati.

    Esempio di vita reale:

    Quando ho una grande discussione accesa sul lavoro, uso un pollo di gomma che tengo sulla mia scrivania proprio per queste occasioni. La persona che detiene il pollo è l’unica persona a cui è permesso parlare. Se non trattieni il pollo non puoi parlare. Puoi solo indicare che vuoi il pollo e aspettare finché non lo ottieni prima di parlare. Una volta che hai finito di parlare, puoi restituire il pollo al moderatore che lo consegnerà alla persona successiva per parlare. Ciò garantisce che le persone non parlino l’una sull’altra e abbiano anche il proprio spazio per parlare.

    Sostituisci Chicken with Mutex e person with thread e in pratica hai il concetto di mutex.

    @Xetius

    Utilizzo in C #:

    Questo esempio mostra come viene utilizzato un object Mutex locale per sincronizzare l’accesso a una risorsa protetta. Poiché ogni thread chiamante è bloccato fino a quando non acquisisce la proprietà del mutex, deve chiamare il metodo ReleaseMutex per rilasciare la proprietà del thread.

     using System; using System.Threading; class Example { // Create a new Mutex. The creating thread does not own the mutex. private static Mutex mut = new Mutex(); private const int numIterations = 1; private const int numThreads = 3; static void Main() { // Create the threads that will use the protected resource. for(int i = 0; i < numThreads; i++) { Thread newThread = new Thread(new ThreadStart(ThreadProc)); newThread.Name = String.Format("Thread{0}", i + 1); newThread.Start(); } // The main thread exits, but the application continues to // run until all foreground threads have exited. } private static void ThreadProc() { for(int i = 0; i < numIterations; i++) { UseResource(); } } // This method represents a resource that must be synchronized // so that only one thread at a time can enter. private static void UseResource() { // Wait until it is safe to enter. Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name); mut.WaitOne(); Console.WriteLine("{0} has entered the protected area", Thread.CurrentThread.Name); // Place code to access non-reentrant resources here. // Simulate some work. Thread.Sleep(500); Console.WriteLine("{0} is leaving the protected area", Thread.CurrentThread.Name); // Release the Mutex. mut.ReleaseMutex(); Console.WriteLine("{0} has released the mutex", Thread.CurrentThread.Name); } } // The example displays output like the following: // Thread1 is requesting the mutex // Thread2 is requesting the mutex // Thread1 has entered the protected area // Thread3 is requesting the mutex // Thread1 is leaving the protected area // Thread1 has released the mutex // Thread3 has entered the protected area // Thread3 is leaving the protected area // Thread3 has released the mutex // Thread2 has entered the protected area // Thread2 is leaving the protected area // Thread2 has released the mutex 

    Riferimento MSDN Mutex