Un mutex est un concept de programmation fréquemment utilisé pour résoudre des problèmes de multi-threading. Ma question à la communauté:
Qu'est-ce qu'un mutex et comment l'utilisez-vous?
Un mutex est un concept de programmation fréquemment utilisé pour résoudre des problèmes de multi-threading. Ma question à la communauté:
Qu'est-ce qu'un mutex et comment l'utilisez-vous?
Réponses:
Lorsque j'ai une grande discussion animée au travail, j'utilise un poulet en caoutchouc que je garde dans mon bureau pour de telles occasions. La personne qui tient le poulet est la seule personne autorisée à parler. Si vous ne tenez pas le poulet, vous ne pouvez pas parler. Vous pouvez seulement indiquer que vous voulez le poulet et attendre de l'avoir avant de parler. Une fois que vous avez fini de parler, vous pouvez remettre le poulet au modérateur qui le remettra à la prochaine personne à parler. Cela garantit que les gens ne se parlent pas entre eux et ont également leur propre espace pour parler.
Remplacez Poulet par Mutex et personne avec du fil et vous avez fondamentalement le concept d'un mutex.
Bien sûr, il n'existe pas de mutex en caoutchouc. Seulement poulet en caoutchouc. Mes chats avaient autrefois une souris en caoutchouc, mais ils l'ont mangée.
Bien sûr, avant d'utiliser le poulet en caoutchouc, vous devez vous demander si vous avez réellement besoin de 5 personnes dans une pièce et ne serait-il pas plus facile qu'une seule personne dans la pièce fasse tout le travail par elle-même. En fait, cela ne fait que prolonger l'analogie, mais vous avez l'idée.
Un Mutex est un drapeau mutuellement exclusif. Il agit comme un gardien de porte à une section de code permettant un thread et bloquant l'accès à tous les autres. Cela garantit que le code contrôlé ne sera touché que par un seul thread à la fois. Assurez-vous simplement de libérer le mutex lorsque vous avez terminé. :)
Exclusion mutuelle. Voici l'entrée Wikipedia à ce sujet:
http://en.wikipedia.org/wiki/Mutual_exclusion
Le but d'un mutex est de synchroniser deux threads. Lorsque vous avez deux threads tentant d'accéder à une seule ressource, le modèle général consiste à avoir le premier bloc de code tentant d'accéder à définir le mutex avant d'entrer le code. Lorsque le deuxième bloc de code tente d'accéder, il voit que le mutex est défini et attend que le premier bloc de code soit terminé (et dé-définit le mutex), puis continue.
Les détails spécifiques de la façon dont cela est accompli varient évidemment considérablement selon le langage de programmation.
Lorsque vous disposez d'une application multithread, les différents threads partagent parfois une ressource commune, telle qu'une variable ou similaire. Cette source partagée est souvent inaccessible en même temps, donc une construction est nécessaire pour garantir qu'un seul thread utilise cette ressource à la fois.
Le concept est appelé "exclusion mutuelle" (Mutex court), et est un moyen de garantir qu'un seul thread est autorisé à l'intérieur de cette zone, en utilisant cette ressource, etc.
La façon de les utiliser est spécifique à la langue, mais est souvent (sinon toujours) basée sur un mutex de système d'exploitation.
Certains langages n'ont pas besoin de cette construction, en raison du paradigme, par exemple la programmation fonctionnelle (Haskell, ML sont de bons exemples).
En C #, le mutex commun utilisé est le moniteur . Le type est ' System.Threading.Monitor '. Il peut également être utilisé implicitement via l' instruction ' lock (Object) '. Un exemple de son utilisation est lors de la construction d'une classe 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'instruction lock utilisant l'objet lock privé crée une section critique. Obliger chaque thread à attendre la fin du précédent. Le premier thread entrera dans la section et initialisera l'instance. Le deuxième thread attendra, entrera dans la section et récupérera l'instance initialisée.
Toute sorte de synchronisation d'un membre statique peut utiliser l'instruction de verrouillage de la même manière.
Qu'est-ce qu'un Mutex ?
Le mutex (en fait, le terme mutex est l'abréviation d'exclusion mutuelle) également connu sous le nom de spinlock est l'outil de synchronisation le plus simple utilisé pour protéger les régions critiques et ainsi empêcher les conditions de concurrence. C'est-à-dire qu'un thread doit acquérir un verrou avant d'entrer dans une section critique (dans une section critique, plusieurs threads partagent une variable commune, mettant à jour une table, écrivant un fichier, etc.), il libère le verrou lorsqu'il quitte la section critique.
Qu'est-ce qu'une condition de course ?
Une condition de concurrence critique se produit lorsque deux threads ou plus peuvent accéder aux données partagées et qu'ils essaient de les modifier en même temps. Étant donné que l'algorithme de planification des threads peut à tout moment basculer entre les threads, vous ne connaissez pas l'ordre dans lequel les threads tenteront d'accéder aux données partagées. Par conséquent, le résultat de la modification des données dépend de l'algorithme de programmation des threads, c'est-à-dire que les deux threads sont "en course" pour accéder / modifier les données.
Exemple réel:
Lorsque j'ai une grande discussion animée au travail, j'utilise un poulet en caoutchouc que je garde dans mon bureau pour de telles occasions. La personne qui tient le poulet est la seule personne autorisée à parler. Si vous ne tenez pas le poulet, vous ne pouvez pas parler. Vous pouvez seulement indiquer que vous voulez le poulet et attendre de l'avoir avant de parler. Une fois que vous avez fini de parler, vous pouvez remettre le poulet au modérateur qui le remettra à la prochaine personne à parler. Cela garantit que les gens ne se parlent pas entre eux et ont également leur propre espace pour parler.
Remplacez Poulet par Mutex et personne avec du fil et vous avez fondamentalement le concept d'un mutex.
@Xetius
Utilisation en C #:
Cet exemple montre comment un objet Mutex local est utilisé pour synchroniser l'accès à une ressource protégée. Étant donné que chaque thread appelant est bloqué jusqu'à ce qu'il acquière la propriété du mutex, il doit appeler la méthode ReleaseMutex pour libérer la propriété du 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
Il y a quelques bonnes réponses ici, voici une autre grande analogie pour expliquer ce qu'est le mutex :
Pensez à des toilettes simples avec une clé . Quand quelqu'un entre, il prend la clé et les toilettes sont occupées . Si quelqu'un d'autre doit utiliser les toilettes, il doit attendre dans une file d'attente . Lorsque la personne aux toilettes a terminé , elle passe la clé à la personne suivante dans la file d'attente. C'est logique, non?
Convertissez les toilettes de l'histoire en une ressource partagée et la clé en un mutex . Prendre la clé des toilettes (acquérir une serrure) vous permet de l'utiliser. S'il n'y a pas de clé (la serrure est verrouillée), vous devez attendre. Lorsque la clé est rendue par la personne ( relâchez le verrou ), vous êtes libre de l'acquérir maintenant.
Pour comprendre MUTEX au début, vous devez savoir ce qu'est une "condition de concurrence" et ensuite vous seul comprendrez pourquoi MUTEX est nécessaire. Supposons que vous ayez un programme multithread et que vous ayez deux threads. Maintenant, vous avez un travail dans la file d'attente des travaux. Le premier thread vérifiera la file d'attente des travaux et après avoir trouvé le travail, il commencera à l'exécuter. Le deuxième thread vérifiera également la file d'attente des travaux et trouvera qu'il y a un travail dans la file d'attente. Ainsi, il affectera également le même pointeur de tâche. Donc, maintenant ce qui se passe, les deux threads exécutent le même travail. Cela entraînera un défaut de segmentation. Ceci est l'exemple d'une condition de concurrence.
La solution à ce problème est MUTEX. MUTEX est une sorte de verrou qui verrouille un thread à la fois. Si un autre thread veut le verrouiller, le thread est simplement bloqué.
Le sujet MUTEX dans ce lien de fichier pdf vaut vraiment la peine d'être lu.
Les mutex sont utiles dans les situations où vous devez appliquer un accès exclusif à une ressource sur plusieurs processus, où un verrou régulier n'aidera pas car il ne fonctionne que sur des threads.
Mutex: Mutex signifie Mut ual Ex clusion. Cela signifie qu'à la fois un processus / thread peut entrer dans la section critique. Dans la programmation simultanée où plusieurs threads / processus essaient de mettre à jour la ressource partagée (n'importe quelle variable, mémoire partagée, etc.) peut entraîner un résultat inattendu. (Comme le résultat dépend du thread / processus qui obtient le premier accès).
Afin d'éviter un tel résultat inattendu, nous avons besoin d'un mécanisme de synchronisation, qui garantit qu'un seul thread / processus a accès à une telle ressource à la fois.
La bibliothèque pthread prend en charge Mutex.
typedef union
{
struct __pthread_mutex_s
{
***int __lock;***
unsigned int __count;
int __owner;
#ifdef __x86_64__
unsigned int __nusers;
#endif
int __kind;
#ifdef __x86_64__
short __spins;
short __elision;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
# define __PTHREAD_SPINS 0, 0
#else
unsigned int __nusers;
__extension__ union
{
struct
{
short __espins;
short __elision;
# define __spins __elision_data.__espins
# define __elision __elision_data.__elision
# define __PTHREAD_SPINS { 0, 0 }
} __elision_data;
__pthread_slist_t __list;
};
#endif
Il s'agit de la structure du type de données mutex, c'est-à-dire pthread_mutex_t. Lorsque mutex est verrouillé, __lock défini sur 1. Lorsqu'il est déverrouillé, __lock défini sur 0.
Cela garantit qu'aucun processus / threads ne peut accéder à la section critique en même temps.