O Problema das Corridas de Dados
Entenda por que a mutação concorrente não é segura.
O Problema das Corridas de Dados é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 1 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 Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.
O que é uma condição de corrida de dados
Uma condição de corrida de dados ocorre quando duas ou mais linhas de execução acessam simultaneamente a mesma posição de memória, pelo menos um dos acessos é uma escrita e não há sincronização entre elas.
O resultado é um comportamento indefinido: valores corrompidos, falhas ou erros que só aparecem sob carga.
Estado mutável compartilhado
A causa fundamental das condições de corrida de dados é o estado mutável compartilhado. Se várias tarefas puderem ler e gravar a mesma variável, a ordem se tornará imprevisível.
O contador abaixo pode perder incrementos porque count += 1 é uma operação de leitura, alteração e gravação, não uma operação atômica.
final class Counter {
var count = 0
func increment() {
count += 1 // read, add, write: not atomic
}
}Por que os incrementos são perdidos
A instrução count += 1 é compilada em três etapas: carregar o valor, adicionar um e gravá-lo novamente.
Se duas linhas de execução carregarem 5 ao mesmo tempo, ambas gravarão 6, e um dos incrementos desaparecerá.
// Thread A loads 5
// Thread B loads 5
// Thread A stores 6
// Thread B stores 6 <-- lost updateFragmentação de valores maiores
Além das atualizações perdidas, escritas simultâneas em valores que ocupam várias palavras de máquina, como uma estrutura ou um valor de 64 bits em algumas plataformas, podem ser fragmentadas: o leitor vê metade de uma escrita e metade de outra.
struct Point { var x: Double; var y: Double }
var p = Point(x: 0, y: 0)
// Concurrent writes may leave x from one write and y from anotherA correção antiga: lock
Antes da Concorrência do Swift, a solução clássica era usar um lock (exclusão mútua). Apenas uma linha de execução mantém o lock por vez, serializando o acesso.
O uso de lock funciona, mas é fácil empregá-lo incorretamente: desbloqueios esquecidos, deadlocks e inversão de prioridade.
import Foundation
final class SafeCounter {
private let lock = NSLock()
private var count = 0
func increment() {
lock.lock()
defer { lock.unlock() }
count += 1
}
}Filas de despacho seriais
Outra abordagem clássica é uma fila de despacho serial. Todas as alterações são encaminhadas para uma única fila, portanto nunca se sobrepõem.
import Foundation
final class QueueCounter {
private let queue = DispatchQueue(label: "counter")
private var count = 0
func increment() {
queue.async { self.count += 1 }
}
}Por que a sincronização manual é frágil
O uso de lock e de filas depende de disciplina. O compilador não verifica se todos os acessos estão protegidos.
Uma única leitura desprotegida é suficiente para que a condição de corrida retorne. Não há garantia em tempo de compilação.
// Nothing stops a careless reader from doing this:
// let value = counter.count // unsynchronized read = raceA Concorrência do Swift muda o jogo
A Concorrência do Swift transforma a segurança contra condições de corrida de dados em um recurso da linguagem, em vez de uma convenção.
Três ferramentas trabalham juntas: actor para proteger o estado mutável, Sendable para tipos seguros para compartilhamento e o compilador para impor ambos.
actor Counter {
private var count = 0
func increment() { count += 1 }
}Atores serializam o acesso
Um ator garante que apenas uma tarefa execute seu código de alteração por vez. O ambiente de execução serializa o acesso automaticamente.
Você nunca escreve um lock; o modelo de atores fornece a sincronização.
actor BankAccount {
private(set) var balance = 0
func deposit(_ amount: Int) { balance += amount }
}Imposição em tempo de compilação
O compilador impede que você acesse o estado isolado de um ator sem passar pelo ator. As chamadas entre atores tornam-se assíncronas (await).
Isso transforma condições de corrida em erros em tempo de compilação.
let account = BankAccount()
// Must await: balance is actor-isolated
// let b = await account.balanceSendable delimita o que atravessa as linhas de execução
O protocolo Sendable identifica os tipos que podem ser transmitidos com segurança através dos limites de concorrência.
O compilador impede o envio de estado mutável que não seja Sendable para outra tarefa, eliminando a condição de corrida no nível dos tipos.
struct Money: Sendable {
let amount: Int
let currency: String
}Verificação rápida: condições de corrida de dados
Teste sua compreensão sobre o que causa uma condição de corrida de dados.
Recapitulação: o problema das condições de corrida de dados
As condições de corrida de dados surgem quando o estado mutável compartilhado é acessado simultaneamente sem sincronização, produzindo atualizações perdidas, fragmentação e comportamento indefinido.
As soluções antigas, como locks e filas seriais, funcionam, mas não são verificadas e são frágeis. A Concorrência do Swift substitui a convenção pela imposição: actor isola o estado, Sendable delimita o que atravessa os limites e o compilador verifica a segurança. O restante deste curso explora essas ferramentas em detalhes.
Perguntas Frequentes
A aula “O Problema das Corridas de Dados” é grátis?
Sim — o texto completo de “O Problema das Corridas de Dados” é 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 Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.
O que vou aprender em “O Problema das Corridas de Dados”?
Entenda por que a mutação concorrente não é segura. Você pratica Swift 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 Swift Academy?
Nenhuma experiência prévia é necessária. Swift 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 1 de 4.
Quanto tempo leva a aula “O Problema das Corridas de Dados”?
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 Swift Academy?
Sim. Cada aula de Swift 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
- O Problema das Corridas de Dados
- O Protocolo Sendable
- Isolamento de Actors e nonisolated
- Migração para Concorrência Estrita