0Pricing
C++ Academy · Aula

Implementação de uma fila sem bloqueios

Acompanhe o design de uma fila sem bloqueios para um produtor e um consumidor

Implementação de uma fila sem bloqueios é uma aula grátis de C++ Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C++ Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C++ Academy inclui 4 aulas no total.

Por que usar filas sem bloqueio?

Filas com mutexes podem se tornar gargalos sob alta contenção. Uma fila sem bloqueio permite que produtores e consumidores progridam simultaneamente.

SPSC versus MPMC

Duas variantes:

  • SPSC — um produtor, um consumidor (mais simples e rápida)
  • MPMC — vários produtores, vários consumidores (mais geral)

SPSC é a escolha natural quando você controla as duas extremidades.

Esboço de um buffer circular SPSC

Um buffer circular com dois índices: início (consumidor) e fim (produtor). Cada lado atualiza seu próprio índice.

template <typename T, size_t N>
class SpscQueue {
    T buffer_[N];
    std::atomic<size_t> head_{0};
    std::atomic<size_t> tail_{0};
public:
    bool push(const T& v);
    bool pop(T& v);
};

Inserção em SPSC

O produtor verifica os espaços livres, escreve e depois publica atualizando o fim.

bool push(const T& v) {
    const size_t t = tail_.load(std::memory_order_relaxed);
    const size_t next = (t + 1) % N;
    if (next == head_.load(std::memory_order_acquire))
        return false;     // full
    buffer_[t] = v;
    tail_.store(next, std::memory_order_release);
    return true;
}

Remoção em SPSC

O consumidor verifica se há dados, lê e depois publica atualizando o início.

bool pop(T& v) {
    const size_t h = head_.load(std::memory_order_relaxed);
    if (h == tail_.load(std::memory_order_acquire))
        return false;     // empty
    v = buffer_[h];
    head_.store((h + 1) % N, std::memory_order_release);
    return true;
}

Emparelhamento da ordem de memória

O armazenamento com semântica de liberação em tail sincroniza com o carregamento com semântica de aquisição em tail no consumidor (e vice-versa). Sem a ordenação correta, as escritas dos dados poderiam ser reordenadas para depois da atualização do índice.

Preenchimento de linhas de cache

Para evitar o compartilhamento falso, coloque head_ e tail_ em linhas de cache separadas (normalmente a 64 bytes de distância). Use alignas.

alignas(64) std::atomic<size_t> head_{0};
alignas(64) std::atomic<size_t> tail_{0};

MPMC: muito mais difícil

Vários produtores ou consumidores exigem coordenação adicional — normalmente com laços de CAS em índices compartilhados. Existem muitos projetos (fila de Vyukov, fila MS, baseada em ponteiros de risco).

Boost.Lockfree

É difícil criar filas sem bloqueios com qualidade de produção. Use Boost.Lockfree ou ProducerConsumerQueue da Folly em vez de criar sua própria implementação.

Compromissos

Filas sem bloqueios:

  • Maior vazão sob contenção
  • Latência limitada (sem esperar por um bloqueio)
  • Muito mais difíceis de escrever e depurar
  • Erros de ordenação de memória são silenciosos e difíceis de localizar

Teste de código sem bloqueios

Use ThreadSanitizer (-fsanitize=thread) para detectar condições de corrida nos dados. Use testes de estresse com inserções aleatórias de Sleep para revelar erros de ordenação.

Quando a exclusão mútua é suficiente

A maioria dos aplicativos não precisa de filas sem bloqueios. Primeiro faça medições — uma fila protegida por exclusão mútua e bem implementada frequentemente apresenta desempenho adequado, especialmente com processamento em lotes.

Verificação rápida

O que é compartilhamento falso e por que preencher head_ e tail_?

Recapitulação

Uma fila SPSC sem bloqueios usa um buffer circular com o fim pertencente ao produtor e o início pertencente ao consumidor. Use ordenação de aquisição/liberação e preencha os índices para separá-los em linhas de cache distintas. Para MPMC, prefira uma biblioteca testada.

Perguntas Frequentes

A aula “Implementação de uma fila sem bloqueios” é grátis?

Sim — o texto completo de “Implementação de uma fila sem bloqueios” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C++ Academy, atualize para CoddyKit PRO. O curso de C++ Academy inclui 4 aulas no total.

O que vou aprender em “Implementação de uma fila sem bloqueios”?

Acompanhe o design de uma fila sem bloqueios para um produtor e um consumidor Você pratica C++ Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C++ Academy?

Nenhuma experiência prévia é necessária. C++ Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Implementação de uma fila sem bloqueios”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C++ Academy?

Sim. Cada aula de C++ Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. std::atomic e ordens de memória
  2. Padrões de compare-and-swap: CAS
  3. Implementação de uma fila sem bloqueios
  4. Ponteiros de perigo e o problema ABA
← Voltar para C++ Academy