

Seu próximo nível começa aqui
Seu desenvolvimento não pode ter limites. Garanta sua Assinatura Ilimitada e libere uma preparação completa com os melhores professores do Brasil.
No desenvolvimento de algoritmos paralelos de alto desempenho em arquiteturas modernas, dois conceitos amplamente utilizados são a coerência de cache e a consistência de memória. Considere um cenário em que um programador implementa um padrão produtor consumidor simples utilizando uma flag booleana para indicar a disponibilidade de um dado recém-escrito em um buffer compartilhado. Mesmo operando sobre um hardware que garante coerência de cache estrita (como o protocolo MESI), o consumidor ocasionalmente lê dados inconsistentes ou desatualizados após verificar que a flag é verdadeira. Qual primitiva de programação paralela deve ser obrigatoriamente inserida no código para corrigir esse comportamento e qual é a justificativa técnica para sua necessidade?
Deve ser utilizada a primitiva Compare and Swap (CAS) na verificação da flag, pois a leitura de variáveis booleanas em arquiteturas multicore não é atômica por padrão, permitindo leituras parciais de bits (tearing).
É necessário inserir uma barreira de memória (memory fence) de escrita antes de setar a flag no produtor e uma de leitura após verificar a flag no consumidor, pois a coerência de cache garante a propagação dos valores, mas não garante a ordem em que as operações de escrita se tornam visíveis globalmente devido a otimizações de reordenamento do processador.
O programador deve aplicar um Mutex (Mutual Exclusion) em torno de toda a operação de leitura e escrita, pois arquiteturas modernas desligam o protocolo de coerência de cache durante operações de escrita intensiva para economizar largura de banda do barramento.
Deve ser utilizada a primitiva de Transactional Memory (TM) para encapsular o acesso ao buffer, pois o problema descrito é causado pela falsa concorrência (false sharing) entre a linha de cache da flag e a linha de cache dos dados.
É necessário utilizar a diretiva volatile nas variáveis compartilhadas, pois isso instrui o controlador de cache a realizar um write through imediato para a memória principal, contornando a latência imposta pelos buffers de escrita (store buffers) da CPU.