ProgrammationDéveloppeur mobile

Expliquez le fonctionnement de GCD (Grand Central Dispatch) et DispatchQueue en Swift, comment créer correctement du code asynchrone et quelles pièges peuvent survenir lors de la programmation multithread ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question

Grand Central Dispatch (GCD) est apparu dans iOS et macOS en 2009 en tant que système de bas niveau pour organiser le code concurrent et asynchrone (multithreading), basé sur des files d'attente — DispatchQueue. GCD s'est avéré beaucoup plus concis que la gestion manuelle des threads, fournissant une exécution sécurisée des tâches, une synchronisation et une API conviviale.

Problème

L'asynchronicité et le multithreading sont traditionnellement une source de la plupart des problèmes : courses de données, deadlocks, blocages vivants de l'interface et crashes complexes. Une mauvaise utilisation des files d'attente ou des tentatives d'accès à l'UI depuis un thread non principal peuvent entraîner des bugs.

Solution

Swift permet de créer facilement des travaux de fond et de revenir en toute sécurité sur le thread principal pour mettre à jour l'interface à l'aide de files d'attente globales et personnalisées. Utilisez DispatchQueue pour le travail asynchrone et DispatchGroup si vous devez attendre l'achèvement d'un ensemble de tâches asynchrones.

Exemple de code :

let backgroundQueue = DispatchQueue(label: "background", qos: .background) backgroundQueue.async { // s'exécute dans un thread en arrière-plan let image = downloadImage() DispatchQueue.main.async { // mise à jour sécurisée de l'UI imageView.image = image } }

Caractéristiques clés :

  • DispatchQueue.async exécute le bloc de manière asynchrone
  • DispatchQueue.main.async pour les appels sur le thread principal
  • DispatchSemaphore, DispatchGroup, sync, ainsi que qos pour contrôler la priorité des tâches

Questions pièges.

Que se passe-t-il si vous appelez sync sur la file principale depuis le thread principal ?

Cela entraînera un deadlock : le thread principal attend l'exécution de la tâche sur lui-même, et l'application "se fige".

DispatchQueue.main.sync { // DEADLOCK }

Une DispatchQueue.serial peut-elle exécuter des tâches en parallèle ?

Non, une file d'attente serial exécute toujours les tâches une par une, mais si plusieurs files d'attente serial sont créées, elles s'exécutent en parallèle entre elles.

Est-il permis de mettre à jour l'interface en dehors du thread principal ?

Non, toute manipulation de UIKit (ou SwiftUI View rendering) ne peut se faire que depuis DispatchQueue.main. Une violation entraînera un fonctionnement instable et des plantages.

Erreurs typiques et anti-patterns

  • Appel synchrone sur le thread principal (deadlock)
  • Tentative de mise à jour de l'UI depuis un arrière-plan
  • Course de ressources non gérée lors de l'écriture dans des variables partagées
  • Utilisation de la queue globale sans nécessité, manque de queues dédiées

Exemple de la vie réelle

Cas négatif

Dans un thread en arrière-plan, les données sont chargées, l'UI est immédiatement mise à jour — l'application plante parfois ou l'interface se fige. De plus, un état mutable partagé entre les threads est utilisé sans synchronisation.

Avantages :

  • Le code est visuellement concis

Inconvénients :

  • Bugs instables et crashes rarement reproductibles
  • Pertes de performance

Cas positif

Organisation de toutes les mises à jour de l'UI uniquement sur DispatchQueue.main, files d'attente dédiées pour travailler avec de grandes données, utilisation de DispatchGroup pour contrôler l'achèvement des tâches asynchrones.

Avantages :

  • Pas de débordements
  • Division efficace du travail entre les threads
  • Facile à maintenir

Inconvénients :

  • Beaucoup de "transferts" entre les threads, nécessite de la discipline lors du travail avec des ressources partagées