Mutex, le caissier du parc d’attraction

Dans l’univers .NET, le multi-threading est particulièrement utile. Il est toutefois difficile à déboguer (le pas à pas étant soumis au point d’arrêt sur tous les threads) et les conflits sur l’accès aux données sont coutumes. Le Mutex permet plus de maîtrise.

Voici la présentation du Mutex dans la doc Microsoft :

Primitive de synchronisation qui peut également être utilisée pour la synchronisation entre processus.

Dans la pratique, un mutex permet de gérer les threads qui tentent d’accéder à des instructions : il permet par exemple de retenir des thread en attendant qu’un thread ait fini ce qu’il avait à faire.
Techniquement :
  1. Le thread 1 indique au Mutex que ce dernier devra demander aux autre thread d’attendre
  2. Une fois le traitement fait, le thread 1 relâche l’emprise qu’il a sur le mutex (mettant à jour son WaitHandle) qui pourra ainsi laisser passer les autres threads.
  3. Le Mutex, qui retenait les autres threads, va en laisser passer un nouveau
Et tout recommence à l’étape 1
A la manière d’un employé de parc d’attraction, il met en fait en attente les clients (threads) qui veulent accéder à une nacelle disponible (lots d’instruction) jusqu’à ce que le signal indiquant que les nacelles sont vide (WaitHandle) se fasse entendre.
private static Mutex mut = new Mutex();

public void LaMethodeAppeleParPlusieursThreads(){
   
   mut.WaitOne(); // Retient un thread si un précédent accède aux instructions suivantes

   Thread.Sleep(500); // Traitement
   
   mut.ReleaseMutex(); // Met à jour le WaitHandler, permettant au mutex de 
   savoir qu'il peut laisser passer un thread.
}

Ainsi, le Mutex permet simplement de mettre en attente différents threads pendant qu’un traitement spécifique est réalisé par un autre.
Très utile pour des protéger des ressources partagées, notamment lorsque la synchronisation doit dépasser le cadre d’un seul processus (contrairement à lock qui est limité à l’application en cours).

A savoir que la méthode WaitOne() permet notamment de prendre en paramètre un temps maximal d’attente avant abandon. Cette méthode renvoie au bout du laps de temps un booléen, indiquant que le code sera consultable (true) ou ne sera plus consultable par aucun thread (false). Au final, c’est comme si l’employé de parc d’attraction renvoyait tous les clients de la file d’attente si la nacelle de la grande roue ne revient pas au bout d’un moment (elle est peut-être bloquée).

if (mut.WaitOne(1000)) // Un premier thread a pu entrer
{
   Thread.Sleep(5000); // Mais son temps de traitement excède 
   // le temps d'attente autorisé
   
   // Le mutex prendra conscience que le traitement est faisable mais...
   mut.ReleaseMutex();
}
else {
   //...les threads suivant n’accéderont pas à la ressource
   Console.WriteLine("Traitement abandonné, 1 seul thread est passé");
}

Utile pour libérer des threads (performance) ou déclencher une erreur.

Sources
  • https://docs.microsoft.com/fr-fr/dotnet/api/system.threading.mutex?view=netframework-4.7.2

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *