es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué ocurre un bloqueo cuando se utiliza WaitGroup y un canal en Go?

Quiero usar la función setter para enviar los números del 0 al 9 al canal ch1, y la función computer para elevar al cuadrado el número del canal ch1 y luego enviar el resultado al canal ch2. Sin embargo, obtengo un pánico cuando ejecuto este código. ¿Podría alguien explicar por qué ocurrió esta situación? Estoy totalmente confundido.

package main

import (
    "fmt"
    "sync"
)

func setter(ch1 chan int, wg sync.WaitGroup) {
    for i := 0; i < 10; i++ {
        fmt.Println("setter:", i)
        ch1 <- i
    }
    close(ch1)
    wg.Done()
}

func computer(ch1 chan int, ch2 chan int, wg sync.WaitGroup) {
    for {
        tmp, ok := <-ch1
        if !ok {
            fmt.Println("computer: no hay valor en ch1")
            break
        }
        fmt.Println("computer:", tmp*tmp)
        ch2 <- tmp*tmp
    }
    close(ch2)
    wg.Done()
}

func main() {
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    var wg sync.WaitGroup
    wg.Add(2)
    go setter(ch1, wg)
    go computer(ch1, ch2, wg)

    wg.Wait()
}

El error es el siguiente:

setter: 0
setter: 1
setter: 2
computer: 0
computer: 1
setter: 3
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc000196008)
        /usr/local/go/src/runtime/sema.go:56 +0x45
sync.(*WaitGroup).Wait(0xc000196000)
        /usr/local/go/src/sync/waitgroup.go:130 +0x65
main.main()
        /Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:50 +0x13b

goroutine 18 [chan send]:
main.setter(0xc000194000, 0x200000000, 0xc000000000)
        /Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:16 +0x107
created by main.main
        /Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:47 +0xdb

goroutine 19 [chan send]:
main.computer(0xc000194000, 0xc000194070, 0x200000000, 0x0)
        /Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:35 +0x11c
created by main.main
        /Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:48 +0x12d
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El pánico ocurrió debido a una situación de bloqueo en el código. La causa de este bloqueo es que la función setter está intentando escribir datos en el canal ch1, que tiene un tamaño de búfer de 1. Sin embargo, la función computer está esperando leer de ch1 antes de poder comenzar a procesar los datos.

    Cuando la función setter envía los 10 valores al canal ch1, se bloquea en la última operación de envío porque el búfer del canal está lleno, y no puede seguir enviando datos hasta que un receptor lea datos del canal. Sin embargo, la función computer está esperando leer el primer valor de ch1 antes de poder comenzar a procesar. Dado que tanto el remitente como el receptor están bloqueados y no pueden avanzar, el programa termina en un estado de bloqueo.

    Para solucionar esto, puedes aumentar el tamaño del búfer de ch1 para acomodar los 10 valores o utilizar un mecanismo de sincronización diferente para asegurarte de que el remitente y el receptor no estén bloqueados al mismo tiempo. Por ejemplo, puedes usar otro WaitGroup para sincronizar el inicio de la función computer hasta que la función setter haya terminado de enviar datos.

Comments are closed.