Sobes.tech
Junior

Qu'est-ce qu'un deadlock?

sobes.tech IA

Réponse de l'IA

Un deadlock est une situation sans issue en programmation multithread, où deux ou plusieurs threads se bloquent mutuellement en attendant des ressources occupées par d'autres threads du même groupe.

Conditions de survenue d'un deadlock (conditions de Coffman) :

  1. Exclusion mutuelle (Mutual Exclusion) : Les ressources ne peuvent pas être utilisées simultanément par plusieurs threads.
  2. Retenue et attente (Hold and Wait) : Les threads qui possèdent déjà une ressource attendent d'en obtenir une autre, occupée par un autre thread.
  3. Sans préemption (No Preemption) : Une ressource ne peut pas être forcée à être retirée d'un thread qui la possède ; elle ne peut être libérée que par le thread lui-même.
  4. Attente circulaire (Circular Wait) : Il existe une chaîne de deux ou plusieurs threads où chaque thread attend une ressource détenue par le suivant dans la chaîne (attente en cercle).

Exemple simple de deadlock :

Deux threads, deux ressources (A et B).

  • Le thread 1 capture la ressource A.
  • Le thread 2 capture la ressource B.
  • Le thread 1 tente de capturer B (qui est occupé par le thread 2).
  • Le thread 2 tente de capturer A (qui est occupé par le thread 1).

Les deux threads sont bloqués pour toujours.

// Exemple simple de simulation de deadlock avec lock
object resourceA = new object();
object resourceB = new object();

void Thread1Method()
{
    lock (resourceA) // Thread 1 capture A
    {
        Console.WriteLine("Thread 1 a capturé la ressource A");
        Thread.Sleep(100); // Petite pause pour démontrer la possibilité de changement de threads
        lock (resourceB) // Thread 1 tente de capturer B
        {
            Console.WriteLine("Thread 1 a capturé la ressource B");
        }
    }
}

void Thread2Method()
{
    lock (resourceB) // Thread 2 capture B
    {
        Console.WriteLine("Thread 2 a capturé la ressource B");
        Thread.Sleep(100); // Petite pause
        lock (resourceA) // Thread 2 tente de capturer A
        {
            Console.WriteLine("Thread 2 a capturé la ressource A");
        }
    }
}

// La création et l'exécution de threads peuvent conduire à un deadlock.
// new Thread(Thread1Method).Start();
// new Thread(Thread2Method).Start();

// Exécuter ce code peut, mais pas nécessairement, démontrer un deadlock,
// car l'ordre d'exécution dépend du planificateur.
// Si le thread 1 capture A et le thread 2 capture B avant que le premier
// ne puisse capturer B, un deadlock se produira.

Prévenir les deadlocks se fait souvent par :

  • L'ordre d'acquisition des ressources (toujours acquérir les ressources dans le même ordre).
  • L'utilisation de méthodes d'acquisition avec timeout (tenter d'acquérir une ressource pendant un temps déterminé).
  • Concevoir sans avoir besoin de maintenir plusieurs verrouillages simultanément.
  • Utiliser des opérations atomiques ou des primitives de synchronisation de niveau supérieur (par exemple, Monitor.TryEnter, ReaderWriterLockSlim).

Les deadlocks sont difficiles à déboguer car ils dépendent de l'ordre d'exécution des threads et ne se manifestent souvent qu'en charge. Visual Studio fournit des outils pour leur détection et leur analyse.