Einführung in Parallelität und Multithreading in Swift
Moderne mobile und Desktop-Anwendungen müssen schnell und reaktionsfähig sein. In der Entwicklung für iOS und macOS spielt die richtige Verwaltung von Parallelität und Multithreading eine Schlüsselrolle. Swift bietet leistungsstarke Werkzeuge für die parallele Ausführung von Aufgaben, angefangen beim klassischen Grand Central Dispatch (GCD) bis hin zum modernen Modell mit async/await und Akteuren.
In diesem Artikel werden wir alle grundlegenden Ansätze für die Arbeit mit Threads in Swift behandeln: von grundlegenden Konzepten bis hin zu fortgeschrittenen Techniken. Sie erfahren, wie Sie Race Conditions, Deadlocks und andere Probleme vermeiden, die für die Multithread-Programmierung typisch sind.
Grand Central Dispatch (GCD) – Der Klassiker des Multithreading
Grand Central Dispatch (GCD) ist eine Low-Level-Bibliothek von Apple zur Verwaltung der parallelen Codeausführung. Sie verwendet Warteschlangen (Dispatch Queues), um Aufgaben auf Threads zu verteilen.
Grundlegende Arten von Warteschlangen
In GCD gibt es zwei Hauptarten von Warteschlangen:
- Serial Queues (serielle Warteschlangen): Aufgaben werden nacheinander in der Reihenfolge ihres Hinzufügens ausgeführt. Ideal zur Synchronisierung des Zugriffs auf Ressourcen.
- Concurrent Queues (parallele Warteschlangen): Aufgaben können gleichzeitig ausgeführt werden, die Reihenfolge der Fertigstellung ist nicht garantiert.
Beispiel für die Arbeit mit GCD
import Foundation
// Erstellen einer seriellen Warteschlangelet serialQueue = DispatchQueue(label: "com.example.serial")
// Erstellen einer parallelen Warteschlangelet concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)
// Asynchrone AusführungserialQueue.async { print("Aufgabe 1 wird im Hintergrund ausgeführt")}
// Synchrone Ausführung (blockiert den aktuellen Thread)serialQueue.sync { print("Aufgabe 2 wird synchron ausgeführt")}
// Arbeiten mit dem HauptthreadDispatchQueue.main.async { print("UI-Update auf dem Hauptthread")}
// Verzögerte AusführungDispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { print("Ausgeführt nach 2 Sekunden")}Dispatch Group – Synchronisierung einer Aufgabengruppe
Mit Dispatch Group können Sie die Fertigstellung einer Gruppe asynchroner Aufgaben verfolgen und Code nach deren Abschluss ausführen.
let group = DispatchGroup()let queue = DispatchQueue.global(qos: .background)
for i in 1...5 { queue.async(group: group) { print("Aufgabe \\(i) gestartet") Thread.sleep(forTimeInterval: Double.random(in: 0.5...2.0)) print("Aufgabe \\(i) abgeschlossen") }}
group.notify(queue: DispatchQueue.main) { print("Alle Aufgaben erledigt! UI wird aktualisiert.")}Modernes async/await in Swift 5.5+
Ab Swift 5.5 hat Apple ein neues Parallelitätsmodell eingeführt, das auf den Schlüsselwörtern async und await basiert. Dies macht asynchronen Code lesbarer und verständlicher.
Definition asynchroner Funktionen
Asynchrone Funktionen werden mit dem Schlüsselwort async gekennzeichnet, ihr Aufruf erfordert await:
import Foundation
// Asynchrone Funktion zum Laden von Datenfunc 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) ?? "No data"}
// Verwendung von async/awaitfunc loadUserProfile() async { do { let userData = try await fetchUserData() await MainActor.run { print("Benutzerdaten: \\(userData)") } } catch { print("Ladefehler: \\(error)") }}
// Starten einer asynchronen AufgabeTask { await loadUserProfile()}Async let – Parallele Ausführung
Das Schlüsselwort async let ermöglicht es, mehrere asynchrone Aufgaben parallel zu starten:
<