Concurrence et multithreading en Swift : guide complet

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction à la concurrence et au multithreading en Swift

Les applications iOS et macOS modernes nécessitent de plus en plus l'exécution de plusieurs tâches simultanément. Qu'il s'agisse de télécharger des données depuis le réseau, de traiter des images ou d'effectuer des calculs mathématiques complexes — une gestion efficace des threads est indispensable. En Swift, la concurrence et le multithreading sont implémentés au plus haut niveau, offrant au développeur des outils puissants et sécurisés.

Dans cet article, nous allons examiner trois approches principales : Grand Central Dispatch (GCD), OperationQueue et le mot-clé moderne async/await, apparu dans Swift 5.5. Vous apprendrez à choisir correctement entre elles et à éviter les erreurs typiques telles que les conditions de course (race condition) et les blocages mutuels (deadlock).

Grand Central Dispatch (GCD) — le classique du multithreading en Swift

Grand Central Dispatch (GCD) est une bibliothèque bas niveau d'Apple qui gère un pool de threads. Le développeur n'a pas besoin de créer et de détruire les threads manuellement — GCD le fait automatiquement, en distribuant les tâches sur les cœurs disponibles du processeur.

Les files d'attente principales de GCD

Dans GCD, il existe deux types de files d'attente : séquentielles (serial) et parallèles (concurrent). Les tâches dans une file séquentielle sont exécutées les unes après les autres, tandis que dans une file parallèle, elles peuvent être lancées simultanément.

// Création d'une file séquentielle
let serialQueue = DispatchQueue(label: "com.example.serial")
serialQueue.async {
    print("Tâche 1")
}
serialQueue.async {
    print("Tâche 2")
}

// Création d'une file parallèle
let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)
concurrentQueue.async {
    print("Tâche parallèle A")
}
concurrentQueue.async {
    print("Tâche parallèle B")
}

Files globales et QoS

GCD fournit des files globales prêtes à l'emploi avec différentes priorités (Quality of Service). Utilisez-les lorsque vous n'avez pas besoin de créer votre propre file :

  • .userInteractive — pour les mises à jour de l'interface utilisateur (priorité la plus élevée)
  • .userInitiated — pour les tâches initiées par l'utilisateur
  • .utility — pour les opérations d'arrière-plan longues
  • .background — pour les tâches non critiques en termes de temps
DispatchQueue.global(qos: .userInitiated).async {
    // Travail lourd
    let result = performComplexCalculation()
    DispatchQueue.main.async {
        // Retour sur le thread principal pour mettre à jour l'UI
        self.updateUI(with: result)
    }
}

Important : Mettez toujours à jour l'interface utilisateur uniquement sur le thread principal (DispatchQueue.main). Ignorer cette règle entraîne des plantages imprévisibles de l'application.

OperationQueue — gestion des dépendances entre tâches

Si GCD est un « couteau suisse », OperationQueue est un planificateur complet avec possibilité d'annulation, de priorisation et de création de dépendances entre les opérations. Chaque opération est une instance de la classe Operation (ou de sa sous-classe BlockOperation).

Création et exécution des opérations

let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 2 // Limite le nombre d'opérations parallèles

let operation1 = BlockOperation {
    print("Opération 1")
}
let operation2 = BlockOperation {
    print("Opération 2")
}

// Ajout d'une dépendance : operation2 commencera seulement après la fin de operation1
operation2.addDependency(operation1)

operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)

Annulation et priorités

Contrairement à GCD, OperationQueue permet d'annuler une opération spécifique ou toute la file :

// Annulation d'une opération
operation1.cancel()

// Annulation de toute la file
operationQueue.cancelAllOperations()

// Définition de la priorité
operation1.                

Blogs

Book Recommendations