1. 案例1,无缓冲信道导致死锁, -> 运行死锁
// 不设定容量创建的是无缓冲信道,在接收者未准备好之前信道处于阻塞状态,
package main
func main(){
// 例如本案例:fatal error: all goroutines are asleep - deadlock!
// sch := make(chan string)
// sch <- "string"
// fmt.Println(<-sch)
// 处理方法,使用双协程,并且接收者在发送者就绪之前,-> 运行正常
// sch := make(chan string)
//
// go func() {
// fmt.Println(<-sch) // 接收者就绪
// }()
//
// time.Sleep(time.Second)
// sch <- "string"
}
2.案例2,改用有缓冲的信道, -> 运行正常
package main
func main() {
// 案例2,改用有缓冲的信道, -> 运行正常
// sch := make(chan string, 1)
// sch <- "hello"
// fmt.Println(<-sch)
// 有缓冲信道导致的死锁,因信道容量满了,再向信道添加数据会产生阻塞,后续无法消费,从而导致死锁 - >运行死锁
// sch := make(chan string, 1)
// sch <- "hello"
// sch <- "world" // 因信道满了,无法接收数据从而产生阻塞
// fmt.Println(<-sch)
// 解决方法,生产者跟消费者区分开来,使用不同的协程
sch := make(chan int, 1)
go func() {
count := 0
for {
sch <- count
count++
}
close(sch) // 生产者不再生产消息,关闭掉通道即可
}()
go func() {
for {
fmt.Println(<-sch)
}
}()
select {}
}
3. 案例3,消费者一直空等待,并无生产者再生产消息,导致程序阻塞产生死锁 -> 运行死锁
package main
func main() {
// 案例3,消费者一直空等待,并无生产者再生产消息,导致程序阻塞产生死锁 -> 运行死锁
// pipLine := make(chan string)
// go func() {
// pipLine <- "hello world"
// pipLine <- "hello China"
// }()
// // 再无消息消费,造成另一方无穷等待,造成死锁
// // fatal error: all goroutines are asleep - deadlock!
// for data := range pipLine {
// fmt.Println(data)
// }
// 解决方法
// 生产者不再生产消息时,关掉该信道,从而避免消费者傻等待造成死锁
go func() {
pipLine <- "hello world"
pipLine <- "hello China"
close(pipline)
}()
select {}
}
4.案例4,无缓冲通道,当消费者结束,生产者也应该有检测机制,发现消费者没了,应该停止生产,并关闭掉通道,否则会造成死锁,如下代码:
package main
import (
"fmt"
)
var index uint64 = 0
func main() {
// 案例4,无缓冲通道,当消费者结束,生产者也应该有检测机制,发现消费者没了,应该停止生产,并关闭掉通道,否则会造成死锁,如下代码:
// fatal error: all goroutines are asleep - deadlock!
sch := make(chan uint64)
go func() {
count := 0
for {
if count == 10 {
// break // 消费者推出,会造成死锁
}
fmt.Println("read = ", <-sch)
count++
// time.Sleep(time.Second)
}
}()
go func() {
for {
index++
if index == 10 {
index = 0
}
sch <- index
// time.Sleep(time.Second)
}
}()
// 处理方法,生产消费必须同时存在,或者消费者推出,生产者能感知,并且主动关闭掉通道
// 主程
select {}
}