Quão seguro é usar slices no contexto de execução concorrente (Concurrency)?
sobes.tech IA
Resposta da IA
O uso de slices não é seguro no contexto de acesso concorrente sem mecanismos adicionais de sincronização. O acesso múltiplo simultâneo para leitura e escrita ou dois acessos simultâneos para escrita na mesma área de memória (que é o array base do slice) leva a condições de corrida (data race).
Razões para ser inseguro:
- Alteração do array base: Um slice é uma visualização do array base. Operações de adição de elementos (append), especialmente se excederem a capacidade atual, podem levar a uma realocação e cópia de dados para um novo array base. Se, nesse momento, outra goroutine tentar ler ou escrever no array base antigo ou novo, ocorre uma condição de corrida.
- Alteração no cabeçalho do slice: O cabeçalho do slice (uma estrutura que contém um ponteiro para o array base, o comprimento e a capacidade) também pode ser alterado durante operações como
append. Leitura e escrita simultâneas nesse cabeçalho sem bloqueios levam a um comportamento indefinido.
Mecanismos para garantir a segurança:
-
sync.Mutex/sync.RWMutex: Bloqueia o acesso ao slice antes de cada operação de leitura ou escrita.sync.RWMutexé preferido em cenários com leituras frequentes e escritas raras.import "sync" type SafeSlice struct { mu sync.RWMutex items []int } func (s *SafeSlice) Append(item int) { s.mu.Lock() // Bloqueia para escrita defer s.mu.Unlock() s.items = append(s.items, item) } func (s *SafeSlice) Get(index int) (int, bool) { s.mu.RLock() // Bloqueia para leitura defer s.mu.RUnlock() if index < 0 || index >= len(s.items) { return 0, false } return s.items[index], true } -
Canais (Channels): Transferência de propriedade dos dados através de canais. Uma goroutine escreve dados, outra os lê do canal. Isso é adequado para cenários de processamento em fluxo de dados.
// Exemplo de uso de canal para transmitir elementos // em um cenário onde uma goroutine produz e outra consome -
sync.Map: Adequado se o slice é usado como base para mapear chaves para valores ou em cenários onde a ordem não importa, mas a segurança concorrente é crítica.
Conclusão: O uso de slices em cenários concorrentes requer gerenciamento explícito de sincronização para evitar condições de corrida. O acesso simples a um slice de várias goroutines simultaneamente não é seguro.