samedi 1 mars 2025

deadlock

Le deadlock (ou interblocage en français) est un problème classique en programmation concurrente, notamment en C# (et d'autres langages).


🔒 Qu’est-ce qu’un deadlock ?

Un deadlock se produit lorsque deux ou plusieurs threads attendent indéfiniment que des ressources soient libérées par les autres threads, créant une situation où aucun thread ne peut avancer.

C'est comme si deux voitures étaient sur une route étroite, face à face, et que chacune attendait que l'autre recule — mais aucune ne peut ou ne veut le faire.


🧵 Exemple simple en C# :

object lockA = new object();
object lockB = new object();

Thread thread1 = new Thread(() =>
{
    lock (lockA)
    {
        Thread.Sleep(100); // Simule une pause
        lock (lockB)
        {
            Console.WriteLine("Thread 1: Acquired lockA then lockB");
        }
    }
});

Thread thread2 = new Thread(() =>
{
    lock (lockB)
    {
        Thread.Sleep(100);
        lock (lockA)
        {
            Console.WriteLine("Thread 2: Acquired lockB then lockA");
        }
    }
});

thread1.Start();
thread2.Start();

❗ Que se passe-t-il ici ?

  1. thread1 verrouille lockA, puis essaie de verrouiller lockB.

  2. thread2 verrouille lockB, puis essaie de verrouiller lockA.

  3. Les deux attendent l’un l’autre → deadlock.


✅ Comment éviter les deadlocks ?

Voici quelques bonnes pratiques :

1. Toujours verrouiller les objets dans le même ordre

  • Si tous les threads verrouillent les ressources dans le même ordre (par exemple, toujours lockA puis lockB), on évite les blocages circulaires.

2. Utiliser Monitor.TryEnter

  • Permet d’éviter d’attendre indéfiniment un verrou :

bool lockTakenA = false;
bool lockTakenB = false;

try
{
    Monitor.TryEnter(lockA, TimeSpan.FromSeconds(1), ref lockTakenA);
    Monitor.TryEnter(lockB, TimeSpan.FromSeconds(1), ref lockTakenB);

    if (lockTakenA && lockTakenB)
    {
        Console.WriteLine("Safe lock acquisition");
    }
    else
    {
        Console.WriteLine("Failed to acquire both locks");
    }
}
finally
{
    if (lockTakenA) Monitor.Exit(lockA);
    if (lockTakenB) Monitor.Exit(lockB);
}

3. Éviter les locks imbriqués quand c’est possible

  • Plus tu imbriques de lock, plus le risque augmente. Garde le code sous lock le plus court possible.

4. Utiliser des outils comme ConcurrentDictionary, SemaphoreSlim, async/await

  • Ils sont plus sûrs et conçus pour éviter ces problèmes.


Si tu veux, je peux te créer un exemple complet avec une solution de prévention. Tu veux que je t’en montre un ?

Aucun commentaire:

Enregistrer un commentaire

deadlock Lượt xem: