Sobes.tech
Middle+

Quel est l'exemple le plus marquant d'un deadlock dans iOS que vous pouvez donner?

sobes.tech IA

Réponse de l'IA

L’exemple le plus évident de deadlock en iOS se produit lorsqu’on tente de mettre à jour l’interface utilisateur depuis un thread en arrière-plan sans utiliser de mécanismes spéciaux.

// Ce code provoquera un deadlock ou un crash (selon la version d’iOS et le contexte)
// lorsqu’il est appelé depuis un thread non principal
DispatchQueue.global().async {
    // Effectuer un travail en arrière-plan...
    print("Travail en arrière-plan en cours")

    // Tenter de mettre à jour l’UI directement depuis un thread en arrière-plan
    // Cela provoquera une exception ou un deadlock, car UIKit n’est pas thread-safe
    DispatchQueue.main.syncが必要です!
    // Ceci a été ajouté pour démontrer le problème, il ne faut pas faire cela en code réel!
    DispatchQueue.main.sync {
        // Tenter de mettre à jour une étiquette sur le thread principal
        // Mais comme nous attendons déjà de manière synchrone le thread principal, qui est bloqué
        // par notre propre bloc d’envoi synchrone, un deadlock se produit.
        print("Tentative de mise à jour de l’UI")
        // someLabel.text = "Mis à jour depuis l’arrière-plan" // Exemple de ligne qui causerait le problème
    }
    print("Travail en arrière-plan terminé")
}

Explication :

UIKit (le framework pour construire des interfaces utilisateur en iOS) n’est pas thread-safe. Toutes les opérations sur l’UI doivent être effectuées strictement sur le thread principal (main thread).

Dans l’exemple ci-dessus, si l’on appelle le bloc DispatchQueue.main.sync { ... } depuis un thread en arrière-plan, alors :

  1. Le thread en arrière-plan se bloque et attend que le thread principal exécute le bloc de code qui lui est envoyé.
  2. Le thread principal peut être occupé ou, plus probablement dans ce scénario, attendre la fin d’une opération qui aurait dû être lancée depuis le thread en arrière-plan (bien que dans cet exemple, ce n’est pas le cas, l’envoi synchrone au thread principal depuis un thread en arrière-plan est déjà problématique).
  3. En cas de sync, le thread en arrière-plan ne peut pas terminer son travail tant que le thread principal n’a pas exécuté le bloc envoyé. Si le thread principal est déjà bloqué (par exemple, en attendant la fin d’une opération dans le thread en arrière-plan qui à son tour attend le thread principal, ou simplement occupé), cela crée une boucle d’attente, c’est-à-dire un deadlock.

Solution correcte :

Utiliser un envoi asynchrone au thread principal pour mettre à jour l’UI.

// Solution correcte : mise à jour de l’UI de façon asynchrone sur le thread principal
DispatchQueue.global().async {
    // Effectuer un travail en arrière-plan...
    print("Travail en arrière-plan en cours")

    // Envoyer la mise à jour de l’UI de façon asynchrone au thread principal
    DispatchQueue.main.async {
        print("Mise à jour de l’UI sur le thread principal")
        // someLabel.text = "Mis à jour depuis l’arrière-plan" // Endroit approprié pour mettre à jour l’UI
    }
    print("Travail en arrière-plan terminé")
}

Ici, le thread en arrière-plan n’est pas bloqué lors de l’envoi du bloc au thread principal, permettant à la fois à la tâche en arrière-plan et au thread principal de fonctionner indépendamment, évitant ainsi le deadlock.