Go中chan引发的协程死锁

fatal error: all goroutines are asleep - deadlock!

代码如下

package main

import (
	"fmt"
	"time"
)

func deadLock(c chan string) {
	timeout := time.Millisecond * time.Duration(10)
	tk := time.NewTicker(timeout)
	defer tk.Stop()

	for {
		select {
		case txt := <-c:
			fmt.Println("chan value ",txt)
			return

		case <-tk.C:
			fmt.Println("time out")
			return
		}
	}
}

func main() {
	c :=make(chan string)
	c<-"Hello World"
	go deadLock(c)
	time.Sleep(time.Millisecond)
}

上面代码运行时报错:fatal error: all goroutines are asleep - deadlock!

why ?


我们通过make(chan int)创建了一个信道,由于没有指定chan的大小,这是一个无缓冲区的信道,所以当对这个信道写的时候,会一直阻塞等到某个协程对这个信道读。main函数的执行在go语言中本身就是一个协程的执行,所以在执行到c<-"Hello World"的时候,执行main函数的协程将被阻塞,此时不能再继续往下执行了,所以go deadLock(c)这个函数同样也无法执行到了,就无法读到c中的内容了,所以整个程序阻塞,发生了死锁。

How to solve it ?

程序阻塞的原因是main函数不能继续向下执行了,所以go deadLock(c) 执行不到,那我们在main函数中另开一个协程,让他对c进行写,这样main函数就能继续往下执行。

package main

import (
	"fmt"
	"time"
)

func deadLock(c chan string) {
	timeout := time.Millisecond * time.Duration(10)
	tk := time.NewTicker(timeout)
	defer tk.Stop()

	for {
		select {
		case txt := <-c:
			fmt.Println("chan value",txt)
			return

		case <-tk.C:
			fmt.Println("time out")
			return
		}
	}
}

func writeChan(c chan string) {
	c<-"Hello World"
}

func main() {
	c :=make(chan string)
	go writeChan(c)
	go deadLock(c)
	time.Sleep(time.Millisecond)
}

猜你喜欢

转载自blog.csdn.net/u012460314/article/details/107934929
今日推荐