Sobes.tech
Middle+

¿Qué tan seguro es pasar slices a diferentes goroutines?

sobes.tech AI

Respuesta de la IA

Transmitir slices directamente a diferentes goroutines no es seguro si las goroutines las modifican simultáneamente sin sincronización o si el slice se modifica en una goroutine después de ser pasado (por copia del encabezado) a otra.

Razones de inseguridad:

  • Array base compartido: Los slices son encabezados (puntero al array base, longitud, capacidad) que apuntan a un array base común.
  • Condición de carrera (Race Condition): Escribir simultáneamente en el mismo elemento del array base o cambiar su tamaño desde diferentes goroutines conducirá a condiciones de carrera, resultados impredecibles y errores.

Formas seguras de trabajar con slices en goroutines:

  1. Pasar una copia del slice: Crear una copia completa del slice y pasarla. Esto es seguro, ya que las goroutines trabajan con datos separados.

    // crear una copia completa del slice
    newSlice := make([]int, len(originalSlice))
    copy(newSlice, originalSlice)
    
  2. Usar canales: Pasar los elementos del slice o el slice completo a través de canales. Los canales proporcionan sincronización y aislamiento de datos.

    // pasar elementos a través de un canal
    ch := make(chan int)
    go func() {
        for _, v := range originalSlice {
            ch <- v
        }
        close(ch)
    }()
    
    // pasar el slice a través de un canal
    chSlice := make(chan []int)
    go func() {
        chSlice <- originalSlice // pasar por valor del encabezado, pero el canal sincroniza
                                // importante: no modificar originalSlice después de enviarlo
    }()
    
  3. Sincronización con sync.Mutex o sync.RWMutex: Proteger el acceso al slice usando mutexes. Esto asegura que solo una goroutine pueda modificar el slice en cualquier 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
        }
    }
    

Comparación de enfoques:

Enfoque Seguridad Rendimiento con slices grandes Complejidad
Copia del slice Alta Menor (copiar datos) Simple
Canales Alta Depende (costo de operaciones del canal) Media
Mutexes Alta Alta (si no hay conflictos fuertes) Media

Por lo tanto, pasar el encabezado del slice a diferentes goroutines sin sincronización adicional o copia no es seguro. Es necesario usar uno de los métodos anteriores para garantizar la seguridad de los datos.