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)
          }
        }


}

 

你可能感兴趣的:(Go,channel死锁,golang)