Práctica de programación simultánea de Golang | Mes temático de Go

Los humanos somos una especie altamente concurrente, delicada.

primer conocido

La primera impresión del lenguaje Go es que admite la programación concurrente de forma nativa y utiliza rutinas, que son más livianas que los hilos.

ybk93cwmg3y51.jpg

La diferencia entre procesos, hilos y corrutinas.

  • Un proceso es "una instancia de ejecución de un programa" que actúa como una entidad que asigna recursos del sistema. La creación de procesos debe asignar un espacio de direcciones completo e independiente. El cambio de proceso solo ocurre en modo kernel.
  • Subproceso: un subproceso es un flujo de ejecución de un proceso que ejecuta de forma independiente su propio código de programa. Es la unidad más pequeña del flujo de ejecución del programa y la unidad básica de programación y despacho del procesador. Un proceso puede tener uno o más subprocesos.
  • Corrutinas: Las corrutinas no son procesos o subprocesos, y su ejecución es más como una subrutina o una llamada de función sin un valor de retorno. Las corrutinas concurrentes se pueden crear a nivel de idioma y luego escribir para administrarlas. Subcontrate este paso para que las corrutinas sean menos costosas de ejecutar al mismo tiempo.

a.jpeg

Go implementa la concurrencia más simple

for i := 0; i < 10; i++ {
    go func(n int) {
        fmt.Println(n)
    }(i)
}
复制代码

Práctica del proyecto

Recientemente, un proyecto necesita llamar a varios trabajos al mismo tiempo y esperar a que estos trabajos se completen antes de ejecutarse.

Ejecutar trabajo en serie

Inicialmente, tenemos un método que ejecuta el trabajo y ejecuta todos los trabajos en serie:

func buildJob(name string) {
    ...
}

buildJob("A")
buildJob("B")
buildJob("C")
复制代码

Ejecutar trabajos en paralelo

Debido a que todos los trabajos se pueden ejecutar simultáneamente, no es necesario esperar a que se complete la ejecución del trabajo anterior antes de continuar con la ejecución de otros trabajos. Podemos usar la palabra clave Go gopara habilitar uno rápidamente goroutine, a continuación ejecutaremos tres trabajos al mismo tiempo:

go buildJob("A")
go buildJob("B")
go buildJob("C")
复制代码

esperar a que terminen todos los trabajos

Cómo saber si cada trabajo se ha completado, aquí puede usar channelpara comunicarse y usar para selectverificar el resultado de la ejecución:

func buildJob(ch chan error, name string) {
    var err error
    
    ... // build job
    
    ch <- err // finnaly, send the result into channel
}

func build() error {
    jobCount := 3
    errCh := make(err chan error, jobCount)
    defer close(errCh) // 关闭 channel

    go buildJob(errCh, "A")
    go buildJob(errCh, "B")
    go buildJob(errCh, "C")

    for {
        select {
        case err := <-ch:
            if err != nil {
                return err
            }
        }
        
        jobCount--
        if jobCount <= 0 {
            break
        }
    }
    
    return nil
}
复制代码

problema encontrado

Cuando el trabajo A falla, el buildmétodo return errsale y se ejecuta close(errCh). Sin embargo, en este momento, es posible que los otros dos trabajos B y C aún no se hayan ejecutado, y los resultados se les enviarán al mismo tiempo errCh, pero como errChse , el programa se cerrará panic: send on closed channel.

optimizar código

Al enviar datos al canal, puede usar el segundo valor de los datos recibidos para determinar si el canal está cerrado:

func buildJob(ch chan error, name string) {
    var err error
    
    ... // build job
    
    if _, ok := <-ch; !ok {
        return
    }
    ch <- err // finnaly, send the result into channel
}

func build() error {
    jobCount := 3
    errCh := make(err chan error, jobCount)
    defer close(errCh) // 关闭 channel

    go buildJob(errCh, "A")
    go buildJob(errCh, "B")
    go buildJob(errCh, "C")

    for {
        select {
        case err := <-ch:
            if err != nil {
                return err
            }
        }
        
        jobCount--
        if jobCount <= 0 {
            break
        }
    }
    
    return nil
}
复制代码

Resumir

Parece que la programación concurrente solo necesita una palabra clave gopara ejecutar una goroutine, pero en la práctica real, todavía hay problemas que deben abordarse.

Enlace original: k8scat.com/posts/code-…

Supongo que te gusta

Origin juejin.im/post/6944362687811813412
Recomendado
Clasificación