Go channels and deadlock

后端 未结 3 795
情歌与酒
情歌与酒 2020-12-24 14:23

I\'m trying to understand the Go language. I tried to create two goroutines that chain the flow between them using two channels:

func main() {
c1 := make(cha         


        
相关标签:
3条回答
  • 2020-12-24 15:04

    Go channels created with make(chan int) are not buffered. If you want a buffered channel (that won't necessarily block), make it with make(chan int, 2) where 2 is the size of the channel.

    The thing about unbuffered channels is that they are also synchronous, so they always block on write as well as read.

    The reason it deadlocks is that your first goroutine is waiting for its c2 <- i to finish while the second one is waiting for c1 <- i to finish, because there was an extra thing in c1. The best way I've found to debug this sort of thing when it happens in real code is to look at what goroutines are blocked and think hard.

    You can also sidestep the problem by only using synchronous channels if they're really needed.

    0 讨论(0)
  • 2020-12-24 15:05

    to prevent the channel from overflowing, you can ask for the channel's current capacity and dry it before writing again.

    in my case, the game takes place at 60fps and the mouse moves much faster, so it is always good to check that the channel has been cleared before writing again.

    notice that the previous data is lost

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        // you must specify the size of the channel, 
        // even for just one element, or the code doesn't work
        ch := make( chan int, 1 )
        fmt.Printf("len: %v\n", len(ch))
        fmt.Printf("cap: %v\n\n", cap(ch))
    
        ch <- 1
    
        for i := 0; i != 100; i += 1 {
            fmt.Printf("len: %v\n", len(ch))
            fmt.Printf("cap: %v\n\n", cap(ch))
    
            if cap( ch ) == 1 {
                <- ch
            }
    
            ch <- i
    
            fmt.Printf("len: %v\n", len(ch))
            fmt.Printf("cap: %v\n\n", cap(ch))
        }
        fmt.Printf("end!\n")
    }
    
    0 讨论(0)
  • 2020-12-24 15:06

    nmichaels is right on with his answer, but I thought I'd add that there are ways to figure out where you're deadlocking when debugging a problem like this.

    A simple one is if you're on a Unix-like OS, run the command

    kill -6 [pid]
    

    This will kill the program and give a stack trace for each goroutine.

    A slightly more involved way is to attach gdb.

    gdb [executable name] [pid]
    

    You can examine the stack and variables of the active goroutine as normal, but there's no easy way to switch goroutines that I know of. You can switch OS threads in the usual way, but that might not be enough to help.

    0 讨论(0)
提交回复
热议问题