"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¿Por qué la función `append` no es segura para subprocesos para el acceso simultáneo en Go?

¿Por qué la función `append` no es segura para subprocesos para el acceso simultáneo en Go?

Publicado el 2024-11-11
Navegar:127

Why is `append` function not thread-safe for concurrent access in Go?

Función de adición: no es segura para subprocesos para acceso simultáneo

Cuando se utilizan gorutinas simultáneamente para agregar elementos a un segmento dentro de un bucle for, se producen anomalías en los datos pueden surgir Es posible que aparezcan datos faltantes o en blanco en el segmento resultante, lo que indica posibles carreras de datos.

Esto ocurre porque en Go, ningún valor es intrínsecamente seguro para la lectura y escritura simultáneas. Los sectores, que están representados por encabezados de sector, no son una excepción. El código proporcionado muestra carreras de datos debido al acceso simultáneo:

destSlice := make([]myClass, 0)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        destSlice = append(destSlice, tmpObj)
    }(myObject)
}
wg.Wait()

Para verificar la presencia de carreras de datos, ejecute el siguiente comando:

go run -race play.go

La salida le alertará sobre los datos carreras:

WARNING: DATA RACE
...

Resolución de problemas de simultaneidad

Para resolver este problema, proteja el acceso de escritura a destSlice empleando un sync.Mutex:

var (
    mu        = &sync.Mutex{}
    destSlice = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        mu.Lock()
        destSlice = append(destSlice, tmpObj)
        mu.Unlock()
    }(myObject)
}
wg.Wait()

Como alternativa, considere usar un canal para manejar asincrónicamente los anexos:

var (
    appendChan = make(chan myClass)
    destSlice  = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        appendChan 
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3