Parallelität und Multithreading in Swift: Fortgeschrittene Techniken

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Parallelität und Multithreading in Swift: Fortgeschrittenes Niveau

Parallelität (Concurrency) ist eines der komplexesten und wichtigsten Themen in der Entwicklung für iOS/macOS. Auf fortgeschrittenem Niveau bietet Swift leistungsstarke Werkzeuge: vom klassischen Grand Central Dispatch (GCD) bis zum modernen async/await-Modell und dem strengen Actors-System. In diesem Artikel werden wir untersuchen, wie man Threads effektiv verwaltet, Datenrennen vermeidet und threadsicheren Code schreibt.



1. Grand Central Dispatch (GCD): Arbeiten mit Warteschlangen und Gruppen

GCD bleibt die Grundlage des Multithreading in Swift. Auf fortgeschrittenem Niveau ist es jedoch wichtig, nicht nur den Unterschied zwischen main und global() zu verstehen, sondern auch Abhängigkeiten von Aufgaben verwalten zu können.

Erstellen eigener Warteschlangen

let serialQueue = DispatchQueue(label: "com.pythonlib.serial")let concurrentQueue = DispatchQueue(label: "com.pythonlib.concurrent", attributes: .concurrent)

serialQueue.async { print("Aufgabe 1 in der seriellen Warteschlange")}concurrentQueue.async { print("Aufgabe 2 in der parallelen Warteschlange")}

DispatchGroup: Synchronisierung mehrerer Aufgaben

let group = DispatchGroup()let queue = DispatchQueue.global()

queue.async(group: group) { sleep(1) print("Daten laden 1")}queue.async(group: group) { sleep(2) print("Daten laden 2")}

group.notify(queue: DispatchQueue.main) { print("Alle Ladevorgänge abgeschlossen, UI wird aktualisiert")}

Verwenden Sie DispatchGroup, wenn Sie auf die Fertigstellung mehrerer paralleler Operationen warten müssen (z. B. Bild laden oder JSON parsen).



2. Modernes async/await-Modell und Task

Seit Swift 5.5 hat die Sprache native Unterstützung für Asynchronität durch die Schlüsselwörter async und await erhalten. Dies vereinfacht das Lesen von Code und beseitigt die "Pyramide der Closures".

Deklaration und Aufruf einer asynchronen Funktion

func fetchUserData() async -> String {    // Simulation einer Netzwerkanfrage    try? await Task.sleep(nanoseconds: 2_000_000_000)    return "User data loaded"}

Task { let result = await fetchUserData() print(result) // Gibt "User data loaded" aus}

Parallele Aufrufe mit async let

func loadImage() async -> Data { return Data() }func loadMetadata() async -> String { return "meta" }

Task { async let image = loadImage() async let metadata = loadMetadata() let result = try await (image, metadata) print("Bild: \\(result.0), Metadaten: \\(result.1)")}

async let ermöglicht es, mehrere asynchrone Aufgaben parallel zu starten und auf alle zu warten. Dies ist effizienter als ein sequenzieller Aufruf.



3. Actors: Threadsicherheit auf Sprachebene

Aktoren (Actors) sind ein neuer Mechanismus zum Schutz vor Datenrennen. Sie garantieren, dass der Zugriff auf ihren Zustand automatisch synchronisiert wird.

Definition und Verwendung eines Aktors

actor BankAccount {    private var balance: Double = 0.0        func deposit(amount: Double) {        balance += amount        print("Kontostand nach Einzahlung: \\(balance)")    }        func withdraw(amount: Double) -> Bool {        guard balance >= amount else { return false }        balance -= amount        return true    }        func getBalance() -> Double { balance }}

Task { let account = BankAccount() await account.deposit(amount: 100) let success = await account.withdraw(amount: 50) print("Auszahlung erfolgreich: \\(success)")}

Alle Methoden eines Aktors sind standardmäßig isoliert – sie können nur über await aufgerufen werden. Dies schließt eine versehentliche Änderung von Daten aus mehreren Threads aus.

Nicht isolierte Methoden (nonisolated)

actor Logger {    nonisolated func log(message: String) {        print("Log: \\(message)")\                

Blogs

Buchempfehlungen