一次无聊的写码中,遇到了一个死锁的问题,百思不解特意花了半天的时间研究了一下。过程是这样的:

package main

import (
	"fmt"
)

func main() {
	ch := make(chan int, 5)

	go func() {
		ch <- 1
		ch <- 2
		// 注释掉 range 操作会产生死锁
		//close(ch)
	}()

	fmt.Println("cap:", cap(ch), "len:", len(ch))

	for i := range ch {
		fmt.Println(i)
	}

	//<-ch

	fmt.Println("cap:", cap(ch), "len:", len(ch))
}

// output
cap: 5 len: 0
1
fatal error: all goroutines are asleep - deadlock!
2

goroutine 1 [chan receive]:
main.main()
	/Users/ott002/go/src/t.go:19 +0x201

Process finished with exit code 2

出现 deadlock,奇怪中,变换了许多姿势,仍然依旧。

精简一下代码

package main

func main() {
	ch := make(chan int, 5)
	//ch <- 1
	// deadlock
	<-ch
}

便于分析问题。

何谓死锁? 操作系统有讲过的,所有的线程或进程都在等待资源的释放。如上的程序中, 只有一个goroutine, 所以当你从通道获取数据的话,会锁死信道, 并且阻塞当前 goroutine 等待数据的存入, 也就是所有的goroutine(其实就main线一个)都在等待信道的存入,也就是产生死锁咯。