DispatchQueue è una coda fondamentale di Grand Central Dispatch (GCD) per la gestione di attività asincrone su iOS e macOS. Secondo la Apple Developer Documentation, 2026, DispatchQueue astrae la gestione dei thread dallo sviluppatore attraverso code serial e concurrent. GCD distribuisce automaticamente le attività nel pool di thread di sistema, eliminando la necessità di creare e distruggere thread manualmente.
Punti chiave
DispatchQueue è un oggetto del framework Grand Central Dispatch (GCD) che gestisce l'esecuzione di attività in code di thread di sistema o personalizzate. Grand Central Dispatch è una libreria di basso livello di Apple, disponibile da iOS 4 e macOS 10.6, che astrae completamente la gestione dei thread dallo sviluppatore. GCD utilizza il pool di thread del sistema operativo e scala automaticamente il numero di thread in base al carico del dispositivo.
Lo sviluppatore non deve creare e distruggere thread manualmente — GCD si occupa di questo compito, fornendo una semplice API tramite DispatchQueue. Un'attività sotto forma di closure viene inviata a una coda tramite i metodi sync o async. Nel primo caso, il thread chiamante viene bloccato fino al completamento dell'attività; nel secondo, l'esecuzione continua immediatamente.
Secondo Apple (2026), GCD utilizza un pool di thread di sistema che si adatta al numero di core e al carico corrente della CPU. Una coda concurrent non crea un nuovo thread per ogni attività — GCD riutilizza i thread dal pool, minimizzando il sovraccarico della creazione di thread.
Grand Central Dispatch è composto da tre componenti chiave: code (DispatchQueue), gruppi (DispatchGroup) e semafori (DispatchSemaphore). La coda è l'elemento principale che accetta attività sotto forma di blocchi di codice. DispatchGroup sincronizza l'esecuzione di più attività, mentre DispatchSemaphore limita l'accesso a una risorsa condivisa a un numero specifico di thread.
Ogni coda GCD è associata a una specifica classe QoS (Quality of Service), che informa il sistema sull'importanza dell'attività. Il sistema utilizza la QoS per distribuire il tempo di CPU tra le code, dando priorità alle attività più critiche — come l'aggiornamento dell'interfaccia utente o la gestione dei tocchi dell'utente.
Una coda serial esegue le attività rigorosamente in sequenza, una dopo l'altra. Se tre attività vengono inserite in una coda serial, la seconda inizia solo dopo il completamento completo della prima. Le code serial vengono utilizzate per sincronizzare l'accesso a risorse condivise — ad esempio, un array modificato da più parti del codice.
Una coda concurrent esegue più attività simultaneamente, distribuendole tra i thread disponibili del pool di sistema. Le attività in una coda concurrent vengono avviate in ordine FIFO, ma completate in ordine arbitrario se i loro tempi di esecuzione differiscono. Una coda concurrent non garantisce l'ordine di completamento — solo l'ordine di avvio.
| Parametro | Coda serial | Coda concurrent |
|---|---|---|
| Ordine di esecuzione | Rigorosamente sequenziale | Parallelo |
| Numero di thread | Uno | Più dal pool GCD |
| Applicazione | Protezione risorse condivise | Calcoli indipendenti |
| Coda principale | Sì (thread principale) | No |
| Rischio deadlock | Alto con sync sulla stessa coda | Basso |
Una coda serial è ideale per attività che modificano stato condiviso — scrivere su un file, aggiornare un modello di dati o lavorare con Core Data. L'uso di una coda serial garantisce che due parti di codice non modifichino gli stessi dati contemporaneamente, eliminando le race condition senza blocchi aggiuntivi.
Una coda concurrent è adatta per attività che non dipendono l'una dall'altra: caricare più immagini, richieste di rete parallele o elaborazione batch di dati. GCD decide automaticamente quante attività eseguire simultaneamente in base al numero di core della CPU e al carico attuale del sistema.
QoS (Quality of Service) è un meccanismo di GCD che informa il sistema operativo sull'importanza e l'urgenza di un'attività. Il sistema utilizza la QoS per la pianificazione dei thread: le attività con QoS più alta ricevono più tempo di CPU e vengono avviate prima. Il valore di QoS viene passato durante la creazione di una coda o l'invio di un'attività specifica.
GCD dispone di cinque classi QoS. .userInteractive — la priorità più alta per attività relative all'interfaccia utente. .userInitiated — per attività avviate dall'utente. .utility — per attività in background che mostrano progresso. .background — per attività invisibili all'utente. .default — un livello intermedio tra userInitiated e utility, usato per impostazione predefinita.
Secondo Apple (2026), la selezione errata della QoS è una delle cause comuni di problemi di prestazioni. Eseguire un download in background con QoS .userInteractive consuma risorse dell'interfaccia utente, causando micro-ritardi nelle animazioni. Si consiglia di scegliere la QoS più bassa che offre comunque un tempo di esecuzione accettabile.
Quando si carica un'immagine per la visualizzazione immediata, utilizzare .userInitiated — l'utente si aspetta il risultato. Per il precaricamento della schermata successiva, .utility è sufficiente. La sincronizzazione in background con il server viene eseguita con .background, minimizzando l'impatto sulle attività attive.
DispatchGroup permette di tracciare il completamento di un gruppo di attività. Quando tutte le attività del gruppo sono completate, GCD chiama un gestore notify sulla coda specificata. Questo è particolarmente utile quando si caricano più risorse indipendenti — dati del profilo, elenco amici e impostazioni — dove l'interfaccia deve essere aggiornata solo dopo aver ricevuto tutti i dati.
DispatchGroup supporta una chiamata sincrona wait(), che blocca il thread corrente fino al completamento di tutte le attività. Questo è comodo quando il codice non può continuare senza i risultati del gruppo. La variante asincrona notify() chiama una closure sulla coda specificata dopo il completamento di tutte le attività, senza bloccare il thread chiamante.
DispatchSemaphore controlla l'accesso a una risorsa limitando il numero di accessi concorrenti. Un semaforo con valore iniziale 3 permette al massimo tre attività parallele. La chiamata a wait() decrementa il contatore, signal() lo incrementa. Se il contatore raggiunge lo zero, il thread si blocca fino a quando una risorsa non diventa disponibile.
Vediamo tre esempi pratici di utilizzo di DispatchQueue in Swift. Il primo dimostra una chiamata async di base con ritorno al thread principale, il secondo mostra la sincronizzazione tramite una coda serial, e il terzo utilizza DispatchGroup per richieste parallele.
DispatchQueue.main è la coda serial del thread principale, destinata esclusivamente alle operazioni dell'interfaccia utente. Usatela sempre per aggiornare l'interfaccia dopo aver completato il lavoro in background.
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
let data = self.fetchData()
DispatchQueue.main.async {
self.updateUI(with: data)
}
}
Creare una coda serial personalizzata con un identificatore univoco sincronizza l'accesso a un array mutabile. Tutte le operazioni di lettura e scrittura passano attraverso un'unica coda, eliminando le race condition.
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 permette di lanciare più attività su una coda concurrent e ricevere una notifica quando tutte sono completate. Questo è utile quando si caricano dati per una schermata di profilo.
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()
}
Il deadlock quando si chiama sync su una coda serial è l'errore più comune. Se un'attività su una coda serial chiama queue.sync sulla stessa coda, il thread si blocca per sempre. La coda attende il completamento dell'attività corrente, e l'attività attende il completamento della chiamata sync — un classico blocco reciproco.
Tutte le operazioni con UIKit devono essere eseguite sul thread principale. Xcode rileva questi errori in modalità Debug tramite il Main Thread Checker. Nelle build Release, portano a comportamenti imprevedibili: le animazioni non si avviano, l'interfaccia utente non si aggiorna e possono verificarsi crash.
Creare centinaia di code personalizzate invece di utilizzare code globali è un antipattern. Ogni coda consuma risorse di sistema. Per la maggior parte delle attività, le code concurrent globali con diversi livelli di QoS e una o due code serial per sincronizzare i dati condivisi sono sufficienti.
Quando si eseguono attività di ciclo intensive in termini di risorse su una coda in background senza autoreleasepool, la memoria cresce fino al termine dell'intero ciclo. ARC rilascia gli oggetti solo all'uscita dal pool di autorelease. Avvolgete le iterazioni del ciclo in autoreleasepool { } per un rilascio tempestivo della memoria.
Domande frequenti
OperationQueue è costruita sopra GCD ma fornisce un'API di livello superiore con dipendenze delle operazioni, KVO e supporto per l'annullamento. DispatchQueue è una coda di basso livello per semplici attività async senza gestione delle dipendenze.
GCD non supporta l'arresto di un'attività in esecuzione. Il metodo suspend() sospende solo le nuove attività; quella corrente viene eseguita fino alla fine. L'annullamento richiede un controllo manuale di un flag all'interno del codice dell'attività.
Per una richiesta principale con visualizzazione immediata del risultato — .userInitiated. Per il precaricamento dei dati — .utility. Per la sincronizzazione in background — .background.
GCD non fissa il numero di thread. Il pool di thread si adatta dinamicamente sotto carico, considerando i core della CPU, il carico attuale e la QoS di ogni attività. Il numero massimo è limitato dal sistema.
UIKit non è thread-safe — tutte le sue classi devono essere chiamate solo dal thread principale. La violazione causa comportamenti imprevedibili, aggiornamenti mancati e crash in Produzione.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche