Quão seguro é passar slices para diferentes goroutines?
sobes.tech IA
Resposta da IA
Transmitir slices diretamente para diferentes goroutines não é seguro se as goroutines as modificarem simultaneamente sem sincronização ou se o slice for modificado numa goroutine após ser passado (por cópia do cabeçalho) para outra.
Razões de insegurança:
- Array base compartilhado: Os slices são cabeçalhos (ponteiro para o array base, comprimento, capacidade) apontando para um array base comum.
- Condição de corrida (Race Condition): Escrever simultaneamente no mesmo elemento do array base ou alterar seu tamanho a partir de diferentes goroutines levará a condições de corrida, resultados imprevisíveis e erros.
Formas seguras de trabalhar com slices em goroutines:
-
Passar uma cópia do slice: Criar uma cópia completa do slice e passá-la. Isto é seguro, pois as goroutines trabalham com dados separados.
// criar uma cópia completa do slice newSlice := make([]int, len(originalSlice)) copy(newSlice, originalSlice) -
Usar canais: Passar os elementos do slice ou o slice completo através de canais. Os canais fornecem sincronização e isolamento de dados.
// passar elementos através de um canal ch := make(chan int) go func() { for _, v := range originalSlice { ch <- v } close(ch) }() // passar o slice através de um canal chSlice := make(chan []int) go func() { chSlice <- originalSlice // passar por valor do cabeçalho, mas o canal sincroniza // importante: não modificar originalSlice após o envio }() -
Sincronização com sync.Mutex ou sync.RWMutex: Proteger o acesso ao slice usando mutexes. Isto garante que apenas uma goroutine possa modificar o slice em qualquer momento.
import "sync" var mu sync.Mutex var sharedSlice []int func modifySlice(index, value int) { mu.Lock() defer mu.Unlock() if index < len(sharedSlice) { sharedSlice[index] = value } }
Comparação de abordagens:
| Abordagem | Segurança | Desempenho com slices grandes | Complexidade |
|---|---|---|---|
| Cópia do slice | Alta | Menor (cópia de dados) | Simples |
| Canais | Alta | Depende (custo das operações do canal) | Média |
| Mutexes | Alta | Alta (se não houver conflitos fortes) | Média |
Assim, passar o cabeçalho do slice para diferentes goroutines sem sincronização adicional ou cópia não é seguro. É necessário usar um dos métodos acima para garantir a segurança dos dados.