Pregunta

Medio ambiente: OS X 10.8, GO 1.0.2

Hago un canal con buffer-tamaño 2, entonces si escribo canal tres veces, lanzará un error:

Throw: Todas las goroutinas están dormidas: ¡un punto muerto!

Por supuesto, es correcto.

PERO Si escribo canal cuatro o más veces en las Goroutinas, funciona bien, ¿por qué? La capacidad del canal es 2, ¿por qué las goroutinas ignoran eso o olvidan la configuración de la capacidad? Comento los códigos de canal de lectura, por lo que nadie leerá el canal y guardará la capacidad. También uso el tiempo. Duerme para esperar a que todas las goroutinas terminen su trabajo.

Revise los siguientes códigos: paquete principal

//import "fmt"

func main() {
    c := make(chan int, 2)
    /*c <- 1
    c <- 2
    c <- 3*/
    for i:=0; i<4; i++ {
        go func(i int) {
            c <- i
            c <- 9
            c <- 9
            c <- 9
        }(i)
    }
    time.Sleep(2000 * time.Millisecond)

    /*for i:=0; i<4*2; i++ {
        fmt.Println(<-c)
    }*/
}

¿Alguien daría algunos éxitos? gracias chicos.

¿Fue útil?

Solución

Cuando se amortigua un canal, esto significa que no bloqueará hasta que el búfer esté lleno. Una vez que el búfer está lleno, el envío de Goroutine bloqueará a medida que intente agregar cosas al canal.

Esto significa que esto bloqueará:

c := make(chan int)
c <- 1          // Block here, this is unbuffered !
println(<-c)

Y esto lo hará además bloquear:

c := make(chan int, 2)
c <- 1
c <- 2
c <- 3           // Block here, buffer is full !
println(<-c)

Pero el punto de las goroutinas y el canal es precisamente ejecutar las cosas simultáneamente, por lo que esto funcionará:

c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c)            // ... this line is reached in the main goroutine

Y de manera similar:

c := make(chan int, 2)
go func() {  // `go ...` spawns a goroutine
    c <- 1   // Buffer is not full, no block
    c <- 2   // Buffer is not full, no block
    c <- 3   // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine

En su ejemplo, genera cuatro goroutinas diferentes, que escriben cuatro números en el mismo canal amortiguado. Como el búfer es 2 <16, terminarán bloqueando

Pero el quid del asunto es que la política de Go es Espera solo a la goroutina principal:

La ejecución del programa comienza inicializando el paquete principal y luego invocando la función principal. Cuando la función principal regresa, el programa sale. No espera a que se completen otras goroutinas (no principales).

Esto significa que en su primer ejemplo, el principal Goroutine estaba bloqueando cuando llegó a la línea c <- 3. Como ninguna otra Goroutine pudo hacer algo que pudiera desbloquearlo, el tiempo de ejecución detectó que el programa estaba en punto y informó un error.

En su segundo ejemplo, sin embargo, generado Bloque de goroutinas, mientras que el principal continúa en silencio hasta que alcanza el final de su ejecución, momento en el cual todas las goroutinas generadas (bloqueadas) son asesinadas en silencio, y no se informa ningún error.

Otros consejos

Val ha dado una buena respuesta. Me gustaría agregar un consejo adicional que he encontrado útil.

Cuando aprenda a usar goroutinas, use canales tamponados con cero para comenzar. De esta manera, cuando comete un error, inmediatamente obtendrá un punto muerto, que puede aprender. Debe aprender a escribir un código que no sea de punto muerto, lo que significa aprender trucos como no tener dependencias cíclicas en las relaciones cliente-servidor (suponiendo que sus ruidosas se escriban como clientes o servidores).

El razonamiento sobre la red sin almacenamiento en búfer es más simple, aunque esto podría no ser obvio al principio.

El almacenamiento en búfer es realmente útil, pero debe considerarse como un medio para mejorar el rendimiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top