golang:channel死锁

 如果子协程向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)
          }
        }


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值