goroutine发生死锁的情况

如果使用channel之前没有make,会出现dead lock错误。

至于为什么,等待研读源码补充

func main() {
    var x chan int
    go func() {
        x <- 1
    }()
    <-x
}
/*
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive (nil chan)]:
main.main()
    /Users/kltao/code/go/examples/channl/channel1.go:11 +0x60

goroutine 4 [chan send (nil chan)]:
main.main.func1(0x0
*/

关闭channel的时候可能会发生panic,而不是死锁

  • 重复关闭 channel 会导致 panic。

    func main() {
    	c := make(chan int)
    	go func() {
    		for i := 0; i < 100; i++ {
    			fmt.Println(<-c)
    		}
    	}()
    	close(c)
    	close(c)
    	time.Sleep(time.Second)
    }
    /*
    panic: close of closed channel
    */
    
  • 向关闭的 channel 发送数据会 panic。

    func main() {
    	c := make(chan int)
    	go func() {
    		for i := 0; i < 100; i++ {
    			fmt.Println(<-c)
    		}
    	}()
    	close(c)
    	c <- 11
    	time.Sleep(time.Second)
    }
    /*
    panic: send on closed channel
    */
    
  • 从关闭的 channel 读数据不会 panic,读出 channel 中已有的数据之后再读就是 channel 类似的默认值,比如 chan int 类型的 channel 关闭之后读取到的值为 0。

    func main() {
    	c := make(chan int)
    	go func() {
    		for i := 0; i < 100; i++ {
    			fmt.Println(<-c)
    		}
    	}()
    	close(c)
    	time.Sleep(time.Second)
    }
    

对于上面的第三点,我们需要区分一下:channel 中的值是默认值还是 channel 关闭了。可以使用 ok-idiom 方式,这种方式在 map 中比较常用。val, ok := <-ch

写数据之前,没有其他协程阻塞接收并且没有缓冲可以存,会发生dealock

func main() {
	c := make(chan int)
    //c := make(chan int, 1) // 这里不会deadlock
	c <- 11

	go func() {
		for i := 0; i < 100; i++ {
			fmt.Println(<-c)
		}
	}()
	
	close(c)
	time.Sleep(time.Second)
}
/*
fatal error: all goroutines are asleep - deadlock!

*/
© 2017-2020 版权属于 QXQZX &
原文地址:https://www.cnblogs.com/iQXQZX/p/14009288.html