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 mobiles et de bureau modernes doivent être rapides et réactives. Dans le développement iOS et macOS, la gestion correcte de la concurrence et du multithreading joue un rôle clé. Swift fournit des outils puissants pour l'exécution parallèle de tâches, allant du classique Grand Central Dispatch (GCD) au modèle moderne async/await et aux acteurs.



Dans cet article, nous passerons en revue toutes les approches principales pour travailler avec les threads en Swift : des concepts de base aux techniques avancées. Vous apprendrez à éviter les race conditions, les deadlocks et autres problèmes typiques de la programmation multithread.



Grand Central Dispatch (GCD) — le classique du multithreading



Grand Central Dispatch (GCD) est une bibliothèque bas niveau d'Apple pour gérer l'exécution parallèle du code. Elle utilise des files d'attente (dispatch queues) pour distribuer les tâches entre les threads.



Types principaux de files d'attente



Dans GCD, il existe deux types principaux de files d'attente :



  • Serial queues (files séquentielles) : les tâches s'exécutent les unes après les autres dans l'ordre d'ajout. Idéales pour synchroniser l'accès aux ressources.
  • Concurrent queues (files parallèles) : les tâches peuvent s'exécuter simultanément, l'ordre d'achèvement n'est pas garanti.


Exemple de travail avec GCD



import Foundation

// Création d'une file séquentiellelet serialQueue = DispatchQueue(label: "com.example.serial")

// Création d'une file parallèlelet concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)

// Exécution asynchroneserialQueue.async { print("Tâche 1 exécutée en arrière-plan")}

// Exécution synchrone (bloque le thread actuel)serialQueue.sync { print("Tâche 2 exécutée de manière synchrone")}

// Travail avec le thread principalDispatchQueue.main.async { print("Mise à jour de l'UI sur le thread principal")}

// Exécution différéeDispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { print("Exécuté après 2 secondes")}


Dispatch Group — synchronisation d'un groupe de tâches



Dispatch Group permet de suivre l'achèvement d'un groupe de tâches asynchrones et d'exécuter du code après leur fin.



let group = DispatchGroup()let queue = DispatchQueue.global(qos: .background)

for i in 1...5 { queue.async(group: group) { print("Tâche \\(i) commencée") Thread.sleep(forTimeInterval: Double.random(in: 0.5...2.0)) print("Tâche \\(i) terminée") }}

group.notify(queue: DispatchQueue.main) { print("Toutes les tâches sont terminées ! Mise à jour de l'UI.")}


async/await moderne en Swift 5.5+



Depuis Swift 5.5, Apple a introduit un nouveau modèle de concurrence basé sur les mots-clés async et await. Cela rend le code asynchrone plus lisible et compréhensible.



Définition de fonctions asynchrones



Les fonctions asynchrones sont marquées par le mot-clé async, et leur appel nécessite await :



import Foundation

// Fonction asynchrone de chargement de donnéesfunc fetchUserData() async throws -> String { let url = URL(string: "https://api.example.com/user")! let (data, _) = try await URLSession.shared.data(from: url) return String(data: data, encoding: .utf8) ?? "Aucune donnée"}

// Utilisation de async/awaitfunc loadUserProfile() async { do { let userData = try await fetchUserData() await MainActor.run { print("Données utilisateur : \\(userData)") } } catch { print("Erreur de chargement : \\(error)") }}

// Lancement d'une tâche asynchroneTask { await loadUserProfile()}


Async let — exécution parallèle



Le mot-clé async let permet de lancer plusieurs tâches asynchrones en parallèle :



<                

Blogs

Book Recommendations