DispatchQueue: o que é, fila GCD e fundamentos de multithreading

Autor: IT Sectr Publicado: 2026-03-16 Tempo de leitura: 8 min

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 é a abstração principal do GCD para execução de código assíncrono no iOS
  • Fila serial executa tarefas estritamente em sequência, eliminando condições de corrida
  • Fila concorrente executa várias tarefas em paralelo através do pool de threads do sistema
  • QoS define a prioridade da tarefa — de userInteractive a background
  • DispatchQueue.main é a única fila para atualizar a UIKit na thread principal

O que é DispatchQueue e Grand Central Dispatch

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.

Arquitetura do GCD

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.

Filas serial e concorrente: comparação

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âmetroFila serialFila concorrente
Ordem de execuçãoEstritamente sequencialParalela
Número de threadsUmaVárias do pool do GCD
AplicaçãoProteção de recursos compartilhadosCálculos independentes
Fila principalSim (thread principal)Não
Risco de deadlockAlto ao sync na mesma filaBaixo

Quando escolher uma fila serial

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.

Quando escolher uma fila concorrente

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.

Quality of Service: prioridades de execução de tarefas

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.

Exemplo de uso de QoS

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 e semáforos: sincronização de tarefas

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 para limitar o paralelismo

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.

Exemplos de código com DispatchQueue em Swift

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.

Chamada async básica com retorno ao main

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.

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

Fila serial para proteger um recurso compartilhado

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.

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 para requisições paralelas

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.

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()
}

Erros comuns ao trabalhar com DispatchQueue

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.

Atualizar a UI a partir de uma thread em segundo plano

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.

Criação excessiva de filas personalizadas

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.

Ignorar autoreleasepool em loops

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

Qual é a diferença entre DispatchQueue e OperationQueue?

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.

É possível interromper à força uma tarefa no DispatchQueue?

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.

Qual QoS escolher para uma requisição de rede?

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.

Quantas threads uma fila concorrente usa?

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.

Por que o DispatchQueue.main é obrigatório para UIKit?

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

  • DispatchQueue é a principal ferramenta do Grand Central Dispatch para tarefas assíncronas no iOS e macOS
  • Fila serial executa tarefas sequencialmente, eliminando condições de corrida sem bloqueios
  • Fila concorrente executa tarefas em paralelo através do pool de threads do sistema
  • QoS determina a prioridade da tarefa — de userInteractive a background
  • DispatchGroup sincroniza várias tarefas paralelas com notify na thread principal
  • Deadlock ao sync em uma fila serial ocupada é um erro crítico que requer atenção
  • Thread principal é obrigatória para UIKit — atualize a interface apenas através do DispatchQueue.main

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.

Discutir o projeto

Leia também