all goroutines are asleep - deadlock-Go中协程死锁详解

func testDeadLock(c chan int){
    for{
        fmt.Println(<-c)
    }
}

func main() {
    c :=make(chan int)
    c<-'A'
    go testDeadLock(c)
    time.Sleep(time.Millisecond)
}
————————————————

看上面main函数中,先开了一个通道channel c,然后马上对这个c内写入数据。
然后调协程testDeadLock在c中取数据,结果运行时报错:
fatal error: all goroutines are asleep - deadlock!

这究竟是咋回事呢?
首先我们这里通过make(chan int),开辟的通道是一种无缓冲通道,所以当对这个缓冲通道写的时候,会一直阻塞等到某个协程对这个缓冲通道读(大家发现没有这个与典型的生产者消费者有点不一样,当队列中“内容”已经满了,生产者再生往里放东西才会阻塞,而这里我讲c<-'A’理解为生产,他却是需要等到某个协程读了再能继续运行)。
main函数的执行在go语言中本身就是一个协程的执行,所以在执行到c<-'A’的时候,执行main函数的协程将被阻塞,换句话说main函数被阻塞了,此时不能在继续往下执行了,所以go testDeadLock©这个函数无法执行到了,就无法读到c中的内容了,所以整个程序阻塞,发生了死锁。

如何解决这个问题呢?大家想一下,我们阻塞的原因是main函数不能继续向下执行了,所以go testDeadLock©执行不到,对吧,那我们在main函数中另开一个协程,让他对c进行写(对c进行写的过程不在main函数对应的协程中做),修改后的代码:
————————————————

func test(c chan int){
    c<-'A'
}

func testDeadLock(c chan int){
    for{
        fmt.Println(<-c)
    }
}

func main() {
    //chanDemo()
    c :=make(chan int)
    go test(c)
    go testDeadLock(c)
    time.Sleep(time.Millisecond)

}
————————————————

新增了test函数,在main函数中为test函数开了协程专门执行,让对c的写在test中进行,这样main函数就能继续往下执行,去开一个协程执行testDeadLock函数了,这样一来,虽然刚刚开的test函数中会因为对c的写入发生阻塞但并不会影响main函数对应协程的继续执行,所以之后的testDeadLock马上将从c中读出test函数刚刚写入的内容,这样一来 test中对c写入的内容就被testDeadLock顺利读出并打印了。

————————————————

https://blog.csdn.net/u011328417/article/details/89473323

您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
本站大部分内容收集于互联网,如果有侵权内容、不妥之处,请联系删除。敬请谅解!

  Previous post 鲜衣怒马 绝代风华
Next post   分布式事务

添加新评论

  关于博主【WANG-FEiHU】

Duplicate
-----------Complicate
--------------------------Appreciate
-----------------------------------------Fate

闻先后,术专攻
三人有师
习得文武艺,货与帝王家
人性不曾变,资本永无眠

-----------花有重开日,人无再少年-----------

  分类目录

  monitor(TD)

只有脚踏实地的人,才能够说:路,就在我的脚下。

无论你选择做什么,追求完美的程度决定你成就的高度。

这个世界最脆弱的是生命,身体健康,很重要。

技术就是一层窗户纸,捅破它吧。

上帝说:你要什么便取什么,但是要付出相当的代价。

现在站在什么地方不重要,重要的是你往什么方向移动。