DispatchQueue é uma fila fundamental do Grand Central Dispatch (GCD) para gerenciar tarefas assíncronas no iOS e macOS. De acordo com a Apple Developer Documentation, 2026, DispatchQueue abstrai o gerenciamento de threads do desenvolvedor através de filas serial e concorrente. O GCD distribui automaticamente as tarefas pelo pool de threads do sistema, eliminando a necessidade de criar e destruir threads manualmente.
Principais pontos
DispatchQueue é um objeto do framework Grand Central Dispatch (GCD) que gerencia a execução de tarefas em filas de threads do sistema ou personalizadas. Grand Central Dispatch é uma biblioteca de baixo nível da Apple, disponível desde o iOS 4 e macOS 10.6, que abstrai completamente o gerenciamento de threads do desenvolvedor. O GCD usa o pool de threads do sistema operacional e escala automaticamente o número de threads de acordo com a carga do dispositivo.
O desenvolvedor não precisa criar e destruir threads manualmente — o GCD cuida dessa tarefa, fornecendo uma API simples através do DispatchQueue. Uma tarefa na forma de um closure é enviada para uma fila através dos métodos sync ou async. No primeiro caso, a thread chamadora é bloqueada até a conclusão da tarefa; no segundo, a execução continua imediatamente.
De acordo com a Apple (2026), o GCD usa um pool de threads do sistema que se adapta ao número de núcleos e à carga atual da CPU. Uma fila concorrente não cria uma nova thread para cada tarefa — o GCD reutiliza threads do pool, minimizando a sobrecarga de criação de threads.
O Grand Central Dispatch consiste em três componentes principais: filas (DispatchQueue), grupos (DispatchGroup) e semáforos (DispatchSemaphore). A fila é o elemento principal que aceita tarefas na forma de blocos de código. O DispatchGroup sincroniza a execução de múltiplas tarefas, enquanto o DispatchSemaphore limita o acesso a um recurso compartilhado a um número específico de threads.
Cada fila do GCD está associada a uma classe QoS (Quality of Service) específica, que informa ao sistema sobre a importância da tarefa. O sistema usa o QoS para distribuir o tempo de CPU entre as filas, priorizando as tarefas mais críticas — como atualização da UI ou manipulação de toques do usuário.
Uma fila serial executa tarefas estritamente em sequência, uma após a outra. Se três tarefas forem colocadas em uma fila serial, a segunda só começa após a primeira ter sido totalmente concluída. Filas seriais são usadas para sincronizar o acesso a recursos compartilhados — por exemplo, um array modificado por várias partes do código.
Uma fila concorrente executa várias tarefas simultaneamente, distribuindo-as entre as threads disponíveis do pool do sistema. As tarefas em uma fila concorrente são iniciadas em ordem FIFO, mas concluídas em ordem arbitrária se seus tempos de execução forem diferentes. Uma fila concorrente não garante a ordem de conclusão — apenas a ordem de início.
| Parâmetro | Fila serial | Fila concorrente |
|---|---|---|
| Ordem de execução | Estritamente sequencial | Paralela |
| Número de threads | Uma | Várias do pool do GCD |
| Aplicação | Proteção de recursos compartilhados | Cálculos independentes |
| Fila principal | Sim (thread principal) | Não |
| Risco de deadlock | Alto ao sync na mesma fila | Baixo |
Uma fila serial é ideal para tarefas que modificam estado compartilhado — escrever em um arquivo, atualizar um modelo de dados ou trabalhar com Core Data. Usar uma fila serial garante que duas partes do código não modifiquem os mesmos dados simultaneamente, eliminando condições de corrida sem bloqueios adicionais.
Uma fila concorrente é adequada para tarefas que não dependem umas das outras: carregar várias imagens, requisições de rede paralelas ou processamento em lote de dados. O GCD decide automaticamente quantas tarefas executar simultaneamente com base no número de núcleos da CPU e na carga atual do sistema.
QoS (Quality of Service) é um mecanismo do GCD que informa ao sistema operacional sobre a importância e urgência de uma tarefa. O sistema usa o QoS para o agendamento de threads: tarefas com QoS mais alto recebem mais tempo de CPU e são iniciadas antes. O valor de QoS é passado ao criar uma fila ou ao enviar uma tarefa específica.
O GCD tem cinco classes de QoS disponíveis. .userInteractive — a maior prioridade para tarefas relacionadas à UI. .userInitiated — para tarefas iniciadas pelo usuário. .utility — para tarefas em segundo plano que mostram progresso. .background — para tarefas invisíveis ao usuário. .default — um nível intermediário entre userInitiated e utility, usado por padrão.
De acordo com a Apple (2026), a seleção incorreta de QoS é uma das causas comuns de problemas de desempenho. Executar um download em segundo plano com QoS .userInteractive consome recursos da UI, causando micro-lags em animações. Recomenda-se escolher o QoS mais baixo que ainda forneça um tempo de execução aceitável.
Ao carregar uma imagem para exibição imediata, use .userInitiated — o usuário espera o resultado. Para pré-carregar a próxima tela, .utility é suficiente. A sincronização em segundo plano com o servidor é executada com .background, minimizando o impacto nas tarefas ativas.
DispatchGroup permite rastrear a conclusão de um grupo de tarefas. Quando todas as tarefas do grupo são concluídas, o GCD chama um manipulador notify na fila especificada. Isso é especialmente útil ao carregar vários recursos independentes — dados de perfil, lista de amigos e configurações — onde a interface só deve ser atualizada após receber todos os dados.
DispatchGroup suporta uma chamada síncrona wait(), que bloqueia a thread atual até que todas as tarefas sejam concluídas. Isso é conveniente quando o código não pode continuar sem os resultados do grupo. A variante assíncrona notify() chama um closure na fila especificada após todas as tarefas serem concluídas, sem bloquear a thread chamadora.
DispatchSemaphore controla o acesso a um recurso limitando o número de acessos concorrentes. Um semáforo com valor inicial 3 permite no máximo três tarefas paralelas. Chamar wait() decrementa o contador, signal() o incrementa. Se o contador chegar a zero, a thread bloqueia até que um recurso esteja disponível.
Vejamos três exemplos práticos de uso do DispatchQueue em Swift. O primeiro demonstra uma chamada async básica com retorno à thread principal, o segundo mostra a sincronização através de uma fila serial, e o terceiro usa DispatchGroup para requisições paralelas.
DispatchQueue.main é a fila serial da thread principal, destinada exclusivamente a operações de UI. Use-a sempre para atualizar a interface após concluir o trabalho em segundo plano.
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
let data = self.fetchData()
DispatchQueue.main.async {
self.updateUI(with: data)
}
}
Criar uma fila serial personalizada com um identificador único sincroniza o acesso a um array mutável. Todas as operações de leitura e escrita passam por uma única fila, eliminando condições de corrida.
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 permite lançar várias tarefas em uma fila concorrente e receber uma notificação quando todas forem concluídas. Isso é útil ao carregar dados para uma tela de perfil.
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()
}
Deadlock ao chamar sync em uma fila serial é o erro mais comum. Se uma tarefa em uma fila serial chama queue.sync na mesma fila, a thread bloqueia para sempre. A fila espera a tarefa atual terminar, e a tarefa espera a chamada sync terminar — um bloqueio mútuo clássico.
Todas as operações com UIKit devem ser realizadas na thread principal. O Xcode detecta esses erros no modo Debug através do Main Thread Checker. Em compilações Release, eles levam a comportamento imprevisível: animações não iniciam, a UI não atualiza e podem ocorrer crashes.
Criar centenas de filas personalizadas em vez de usar filas globais é um antipadrão. Cada fila consome recursos do sistema. Para a maioria das tarefas, filas concorrentes globais com diferentes níveis de QoS e uma ou duas filas seriais para sincronizar dados compartilhados são suficientes.
Ao executar tarefas de loop com uso intensivo de recursos em uma fila em segundo plano sem autoreleasepool, a memória cresce até o final de todo o loop. O ARC só libera objetos ao sair do autorelease pool. Envolva as iterações do loop em autoreleasepool { } para liberação oportuna de memória.
Perguntas frequentes
OperationQueue é construída sobre o GCD, mas fornece uma API de nível superior com dependências de operação, KVO e suporte a cancelamento. DispatchQueue é uma fila de baixo nível para tarefas async simples sem gerenciamento de dependências.
O GCD não suporta interromper uma tarefa em execução. O método suspend() apenas pausa novas tarefas; a atual é executada até o final. O cancelamento requer uma verificação manual de sinalização dentro do código da tarefa.
Para uma requisição principal com exibição imediata do resultado — .userInitiated. Para pré-carregamento de dados — .utility. Para sincronização em segundo plano — .background.
O GCD não fixa o número de threads. O pool de threads escala dinamicamente sob carga, considerando os núcleos da CPU, a carga atual e o QoS de cada tarefa. O número máximo é limitado pelo sistema.
UIKit não é thread-safe — todas as suas classes devem ser chamadas apenas da thread principal. A violação causa comportamento imprevisível, atualizações perdidas e crashes em Produção.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também