如果子协程向channel中发送完后不关闭channel,主协程在从channel中取完数据后继续取数据,会发生死锁
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int, 10)
go func() {
for i := 0; i < 10; i++ {
ch1 <- i
}
}()
time.Sleep(5 * time.Second)
for i := 0; i < 20; i++ {
a := <-ch1
fmt.Println(a)
}
}
/*
0
1
2
3
4
5
6
7
8
9
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
D:/Go_Work/test15/test.go:17 +0xab
exit status 2
*/
如果子协程向channel中发送完后关闭channel,主协程在从channel中取数据时不会发送死锁
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int, 10)
go func() {
for i := 0; i < 10; i++ {
ch1 <- i
}
close(ch1)
}()
time.Sleep(5 * time.Second)
for i := 0; i < 20; i++ {
a := <-ch1
fmt.Println(a)
}
}
/*
0
1
2
3
4
5
6
7
8
9
0
0
0
0
0
0
0
0
0
0
*/
如果子协程向channel中发送完后不关闭channel,主协程在从channel中取完数据后不再取数据,或者只取了部分数据,不会发生死锁
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int)
go func() {
for i := 0; i < 10; i++ {
ch1 <- i
}
}()
time.Sleep(2 * time.Second)
for i := 0; i < 10; i++ {
a := <-ch1
fmt.Println(a)
}
}
/*
0
1
2
3
4
5
6
7
8
9
*/
一个协程内,如果channel内没有了数据,仍然继续取数据,会发生死锁
import (
"fmt"
//"time"
)
func main() {
ch1 := make(chan int, 10)
for i := 0; i < 3; i++ {
ch1 <- i
}
for i := 0; i < 7; i++ {
a := <-ch1
fmt.Println(a)
}
}
/*
0
1
2
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
D:/Go_Work/test15/test.go:16 +0xae
exit status 2
*/
一个协程内,如果channel数据没取完,不会发生死锁
package main
import (
"fmt"
//"time"
)
func main() {
ch1 := make(chan int, 10)
for i := 0; i < 7; i++ {
ch1 <- i
}
for i := 0; i < 3; i++ {
a := <-ch1
fmt.Println(a)
}
}
/*
0
1
2
*/
从一个没数据的缓冲channel中取数据,会发生死锁
package main
import (
"fmt"
)
func main() {
ch1 := make(chan int, 5)
for i := 0; i < 10; i++ {
a := <-ch1
fmt.Println(a)
}
}
/*
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
D:/Go_Work/test15/test2.go:11 +0x77
exit status 2
*/
总结:从一个没有数据的缓冲channel中取数据,会发生死锁,如果有数据或者关闭的channel中取数据不会死锁。
用select方式处理channel数据,避免死锁:
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int, 5)
go func() {
for i := 0; i < 100; i++ {
time.Sleep(3*time.Second)
ch1<-i
}
}()
for {
select {
case a := <-ch1:
fmt.Println("get a:%d",a)
case <-time.After(2*time.Second):
fmt.Println("do no thing")
}
}
}
/*
do no thing
get a:%d 0
do no thing
get a:%d 1
do no thing
get a:%d 2
do no thing
get a:%d 3
do no thing
get a:%d 4
do no thing
*/
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan int, 5)
go func() {
for i := 0; i < 100; i++ {
time.Sleep(1*time.Second)
ch1<-i
}
}()
for {
select {
case a := <-ch1:
fmt.Println("get a:%d",a)
}
}
}