DispatchQueue: wat het is, GCD-wachtrij en basis van multi-threading

Auteur: IT Sectr Gepubliceerd: 2026-03-16 Leestijd: 8 min

DispatchQueue is een fundamentele wachtrij van het Grand Central Dispatch (GCD) framework voor het beheren van asynchrone taken in iOS en macOS. Volgens Apple Developer Documentation, 2026 abstraheert DispatchQueue het threadbeheer van de ontwikkelaar via serial en concurrent wachtrijen. GCD verdeelt taken automatisch over de systeemthreadpool, waardoor handmatig maken en vernietigen van threads overbodig wordt.

Belangrijkste punten

  • DispatchQueue — de belangrijkste abstractie van GCD voor asynchrone code-uitvoering in iOS
  • Serial wachtrij voert taken strikt sequentieel uit, waardoor race-omstandigheden worden geëlimineerd
  • Concurrent wachtrij voert meerdere taken parallel uit via de systeemthreadpool
  • QoS bepaalt de prioriteit van een taak — van userInteractive tot background
  • DispatchQueue.main — de enige wachtrij voor het bijwerken van UIKit op de hoofdthread

Wat is DispatchQueue en Grand Central Dispatch

DispatchQueue is een object van het Grand Central Dispatch (GCD) framework dat de uitvoering van taken in systeem- of aangepaste threadwachtrijen beheert. Grand Central Dispatch is een低-niveau Apple-bibliotheek, beschikbaar sinds iOS 4 en macOS 10.6, die threadbeheer volledig abstraheert van de ontwikkelaar. GCD gebruikt de threadpool van het besturingssysteem en schaalt het aantal threads automatisch op basis van de belasting van het apparaat.

De ontwikkelaar hoeft geen threads handmatig te maken en te vernietigen — GCD neemt deze taak over en biedt een eenvoudige API via DispatchQueue. Een taak in de vorm van een closure wordt via de methoden sync of async naar de wachtrij gestuurd. In het eerste geval wordt de aanroepende thread geblokkeerd tot de taak is voltooid, in het tweede geval gaat deze onmiddellijk verder met uitvoeren.

Volgens Apple (2026) gebruikt GCD de systeemthreadpool die zich aanpast aan het aantal cores en de huidige belasting van de processor. Een concurrent wachtrij maakt geen nieuwe thread aan voor elke taak — GCD hergebruikt threads uit de pool, wat de overhead van het maken van threads minimaliseert.

GCD-architectuur

Grand Central Dispatch bestaat uit drie belangrijke componenten: de wachtrij (DispatchQueue), de groep (DispatchGroup) en de semafoor (DispatchSemaphore). De wachtrij is het belangrijkste element dat taken ontvangt in de vorm van codeblokken. DispatchGroup synchroniseert de uitvoering van meerdere taken, en DispatchSemaphore beperkt de toegang tot een gedeelde bron tot een specifiek aantal threads.

Elke GCD-wachtrij is gekoppeld aan een specifieke QoS (Quality of Service)-klasse die het systeem informeert over het belang van de taak. Het systeem gebruikt QoS om processortijd te verdelen tussen wachtrijen, waarbij prioriteit wordt gegeven aan kritiekere taken — bijvoorbeeld UI-updates of verwerking van gebruikersaanrakingen.

Serial en Concurrent wachtrijen: vergelijking

Serial wachtrij voert taken strikt sequentieel uit, de een na de ander. Als drie taken in een serial wachtrij worden geplaatst, begint de tweede pas nadat de eerste volledig is voltooid. Serial wachtrijen worden gebruikt voor het synchroniseren van toegang tot gedeelde bronnen — bijvoorbeeld een array die vanuit meerdere delen van de code wordt gewijzigd.

Concurrent wachtrij voert meerdere taken tegelijkertijd uit en verdeelt ze over beschikbare threads uit de systeempool. Taken in een concurrent wachtrij starten in de volgorde van binnenkomst (FIFO), maar eindigen in willekeurige volgorde als hun uitvoeringstijd verschilt. Concurrent wachtrij garandeert geen volgorde van voltooiing — alleen de volgorde van starten.

ParameterSerial wachtrijConcurrent wachtrij
UitvoeringsvolgordeStrikt sequentieelParallel
Aantal threadsEénMeerdere uit GCD-pool
ToepassingBescherming van gedeelde bronnenOnafhankelijke berekeningen
Main queueJa (hoofdthread)Nee
Deadlock-risicoHoog bij sync op dezelfde wachtrijLaag

Wanneer een serial wachtrij kiezen

Een serial wachtrij is ideaal voor taken die de gedeelde toestand wijzigen — schrijven naar een bestand, het updaten van een gegevensmodel of werken met Core Data. Het gebruik van een serial wachtrij garandeert dat twee stukken code niet tegelijkertijd dezelfde gegevens wijzigen, waardoor race-omstandigheden zonder extra vergrendelingen worden geëlimineerd.

Wanneer een concurrent wachtrij kiezen

Concurrent wachtrij is geschikt voor taken die niet van elkaar afhankelijk zijn: het laden van meerdere afbeeldingen, parallelle netwerkverzoeken of batchverwerking van gegevens. GCD beslist automatisch hoeveel taken er tegelijkertijd worden uitgevoerd, op basis van het aantal processorkernen en de huidige systeembelasting.

Quality of Service: prioriteiten van taakuitvoering

QoS (Quality of Service) — een GCD-mechanisme dat het besturingssysteem informeert over het belang en de urgentie van een taak. Het systeem gebruikt QoS voor het plannen van threads: taken met een hogere QoS krijgen meer processortijd en worden eerder gestart. De QoS-waarde wordt doorgegeven bij het aanmaken van een wachtrij of het verzenden van een specifieke taak.

In GCD zijn vijf QoS-klassen beschikbaar. .userInteractive — de hoogste prioriteit voor UI-gerelateerde taken. .userInitiated — voor taken die door de gebruiker zijn geïnitieerd. .utility — voor achtergrondtaken met weergave van voortgang. .background — voor taken die niet zichtbaar zijn voor de gebruiker. .default — een tussenniveau tussen userInitiated en utility, standaard gebruikt.

Volgens Apple (2026) is een onjuiste QoS-keuze een van de veelvoorkomende oorzaken van prestatieproblemen. Het starten van een achtergronddownload met QoS .userInteractive onttrekt bronnen aan de UI, wat micro-vertragingen in animaties veroorzaakt. Het wordt aanbevolen de laagste QoS te kiezen die nog steeds een acceptabele uitvoeringstijd biedt.

Voorbeeld van QoS-toepassing

Bij het laden van een afbeelding voor onmiddellijke weergave gebruikt u .userInitiated — de gebruiker verwacht een resultaat. Voor het vooraf laden van het volgende scherm is .utility voldoende. Achtergrondsynchronisatie met de server wordt uitgevoerd met .background, waardoor de impact op actieve taken wordt geminimaliseerd.

DispatchGroup en semaforen: taaksynchronisatie

DispatchGroup maakt het mogelijk de voltooiing van een groep taken te volgen. Wanneer alle taken in de groep zijn voltooid, roept GCD de notify-handler aan op de opgegeven wachtrij. Dit is vooral handig bij het laden van meerdere onafhankelijke bronnen — profielgegevens, vriendenlijst en instellingen — wanneer de interface pas moet worden bijgewerkt nadat alle gegevens zijn ontvangen.

DispatchGroup ondersteunt de synchrone aanroep wait(), die de huidige thread blokkeert totdat alle taken zijn voltooid. Dit is handig wanneer de code niet kan doorgaan zonder de resultaten van de groep. De asynchrone variant — notify() — roept de closure aan op de opgegeven wachtrij nadat alle taken zijn voltooid, zonder de aanroepende thread te blokkeren.

DispatchSemaphore voor het beperken van parallellisme

DispatchSemaphore regelt de toegang tot een bron en beperkt het aantal gelijktijdige toegangen. Een semafoor met beginwaarde 3 maakt het mogelijk maximaal drie parallelle taken uit te voeren. Bij aanroep van wait() wordt de teller verlaagd, bij signal() verhoogd. Als de teller nul is, wordt de thread geblokkeerd totdat de bron vrijkomt.

Codevoorbeelden met DispatchQueue in Swift

Laten we drie praktische voorbeelden bekijken van het gebruik van DispatchQueue in Swift. De eerste toont een basis async-aanroep met terugkeer naar de hoofdthread, de tweede — synchronisatie via een serial wachtrij, de derde — DispatchGroup voor parallelle verzoeken.

Basis async-aanroep met terugkeer naar main

DispatchQueue.main is de serial wachtrij van de hoofdthread, uitsluitend bedoeld voor UI-bewerkingen. Gebruik deze altijd om de interface bij te werken na voltooiing van achtergrondwerk.

swift
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
    let data = self.fetchData()
    DispatchQueue.main.async {
        self.updateUI(with: data)
    }
}

Serial wachtrij voor bescherming van gedeelde bron

Het aanmaken van uw eigen serial wachtrij met een unieke identificatie synchroniseert de toegang tot een veranderlijke array. Alle lees- en schrijfbewerkingen gaan door één wachtrij, waardoor race-omstandigheden worden geëlimineerd.

swift
let serialQueue = DispatchQueue(label: "com.app.items")
var items: [Int] = []

serialQueue.async {
    items.append(1)
}
serialQueue.async {
    let last = items.last
    DispatchQueue.main.async {
        print("Last item: \(last)")
    }
}

DispatchGroup voor parallelle verzoeken

DispatchGroup maakt het mogelijk meerdere taken op een concurrent wachtrij te starten en een melding te ontvangen wanneer alle taken zijn voltooid. Dit is handig bij het laden van gegevens voor een profielscherm.

swift
let group = DispatchGroup()
let worker = DispatchQueue.global()

worker.async(group: group) { self.loadProfile() }
worker.async(group: group) { self.loadFriends() }
worker.async(group: group) { self.loadSettings() }

group.notify(queue: DispatchQueue.main) {
    self.showCompleteUI()
}

Veelgemaakte fouten bij het werken met DispatchQueue

Deadlock bij een sync-aanroep op een serial wachtrij — de meest voorkomende fout. Als een taak op een serial wachtrij queue.sync op dezelfde wachtrij aanroept, wordt de thread permanent geblokkeerd. De wachtrij wacht op voltooiing van de huidige taak en de taak wacht op voltooiing van de sync-aanroep — een klassieke wederzijdse blokkade.

UI bijwerken vanuit een achtergrondthread

Alle bewerkingen met UIKit moeten op de hoofdthread worden uitgevoerd. Xcode detecteert deze fouten in de Debug-modus via de Main Thread Checker. In een Release-build leiden ze tot onvoorspelbaar gedrag: animaties starten niet, UI wordt niet bijgewerkt, crashes zijn mogelijk.

Overmatig aanmaken van aangepaste wachtrijen

Het aanmaken van honderden aangepaste wachtrijen in plaats van globale wachtrijen is een antipatroon. Elke wachtrij verbruikt systeembronnen. Voor de meeste taken zijn globale concurrent wachtrijen met verschillende QoS en één of twee serial wachtrijen voor synchronisatie van gedeelde gegevens voldoende.

Negeren van autoreleasepool in loops

Bij het uitvoeren van resource-intensieve cyclische taken op een achtergrondwachtrij zonder autoreleasepool groeit het geheugen tot het einde van de hele loop. ARC maakt objecten pas vrij bij het verlaten van de autorelease pool. Omwikkel loop-iteraties in autoreleasepool { } voor tijdige geheugenvrijgave.

Veelgestelde vragen

Wat is het verschil tussen DispatchQueue en OperationQueue?

OperationQueue is gebouwd bovenop GCD, maar biedt een hoger-niveau API met operationele afhankelijkheden, KVO en ondersteuning voor annulering. DispatchQueue is een低-niveau wachtrij voor eenvoudige async-taken zonder afhankelijkheidsbeheer.

Kan een taak in DispatchQueue gedwongen worden gestopt?

GCD ondersteunt het stoppen van een gestarte taak niet. De methode suspend() pauzeert alleen nieuwe taken, de huidige taak wordt tot het einde uitgevoerd. Voor annulering is handmatige controle van een vlag in de taakcode nodig.

Welke QoS kiezen voor een netwerkverzoek?

Voor het hoofdverzoek met onmiddellijke weergave van het resultaat — .userInitiated. Voor het vooraf laden van gegevens — .utility. Voor achtergrondsynchronisatie — .background.

Hoeveel threads gebruikt een concurrent wachtrij?

GCD legt het aantal threads niet vast. De threadpool schaalt dynamisch onder belasting, rekening houdend met processorkernen, huidige belasting en QoS van elke taak. Het maximale aantal wordt door het systeem beperkt.

Waarom is DispatchQueue.main verplicht voor UIKit?

UIKit is niet thread-safe — al zijn klassen moeten alleen vanuit de hoofdthread worden aangeroepen. Overtreding veroorzaakt onvoorspelbaar gedrag, gemiste updates en crashes in productie.

Samenvatting

  • DispatchQueue — het belangrijkste hulpmiddel van Grand Central Dispatch voor asynchrone taken in iOS en macOS
  • Serial wachtrij voert taken sequentieel uit, waardoor race-omstandigheden zonder vergrendelingen worden geëlimineerd
  • Concurrent wachtrij voert taken parallel uit via de systeemthreadpool
  • QoS bepaalt de prioriteit van een taak — van userInteractive tot background
  • DispatchGroup synchroniseert meerdere parallelle taken met notify op de hoofdthread
  • Deadlock bij sync op een bezette serial wachtrij — kritieke fout die aandacht vereist
  • Main thread is verplicht voor UIKit — update de interface alleen via DispatchQueue.main

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook